RubyのDATAという特殊なグローバル定数
Rubyにはスクリプト言語らしい機能が色々ある。::DATAを使うと、スクリプト本体の後ろにテキストデータを貼り付けておける。
def show_data puts "DATA: #{DATA.class}" DATA.each_line do |l| puts "line: #{l}" end end show_data __END__ 1 2 3
$ ruby data.rb DATA: File line: 1 line: 2 line: 3 $
DATAというのは、Fileオブジェクトで、ruby.c の load_file_internal という関数で初期化されている。
static VALUE load_file_internal(VALUE arg) { : : : : : : if (script && tree && rb_parser_end_seen_p(parser)) { /* * DATA is a File that contains the data section of the executed file. * To create a data section use <tt>__END__</tt>: * * $ cat t.rb * puts DATA.gets * __END__ * hello world! * * $ ruby t.rb * hello world! */ rb_define_global_const("DATA", f); } else if (f != rb_stdin) { rb_io_close(f); } return (VALUE)tree; }
もしかして、これって sinatra のテンプレートでも使われてるのかな? と思って lib/sinatra/base.rb を見てみたら、
# Load embeded templates from the file; uses the caller's __FILE__ # when no file is specified. def inline_templates=(file=nil) file = (file.nil? || file == true) ? (caller_files.first || File.expand_path($0)) : file begin io = ::IO.respond_to?(:binread) ? ::IO.binread(file) : ::IO.read(file) app, data = io.gsub("\r\n", "\n").split(/^__END__$/, 2) rescue Errno::ENOENT app, data = nil end
とあって、__END__を split してた。なんでだろう。