Я изучаю, как использовать class_eval в модулях (я несколько знаком с class_eval), и столкнулся с этим полезным классом в resource_controller. Там у них есть вещи как это:
class_eval <<-"end_eval", __FILE__, __LINE__
def #{block_accessor}(*args, &block)
unless args.empty? && block.nil?
args.push block if block_given?
@#{block_accessor} = [args].flatten
end
@#{block_accessor}
end
end_eval
Что делает __FILE__
и __LINE__
в том контексте? Я знаю __FILE__
ссылается на текущий файл, но что та целая вещь делает точно? Действительно не знайте, как искать это :).
__FILE__
и __LINE__
- это своего рода динамические константы, которые хранят файл и строку, которые выполняются в данный момент. Передача их сюда позволяет ошибкам правильно сообщать об их местоположении.
instance_eval <<-end_eval, __FILE__, __LINE__
def foo
a = 123
b = :abc
a.send b
end
end_eval
foo
Когда вы запускаете это
$ ruby foo.rb
foo.rb:5:in `send': undefined method `abc' for 123:Fixnum (NoMethodError)
from foo.rb:5:in `foo'
from foo.rb:11
Обратите внимание, что он указывает файл и строку #5, даже если это был просто текст в eval. Без этого трюка с файлом и строкой вывод выглядел бы так:
$ ruby foo.rb
(eval):5:in `send': undefined method `abc' for 123:Fixnum (NoMethodError)
from (eval):5:in `foo'
from foo.rb:11
Трассировка стека просто показывает (eval)
, что не так полезно.
<<
- это начало heredoc . Эта строка является началом многострочной строки. Строка преобразована для создания функции. Функция class_eval использует __FILE__ и __LINE__ для добавления отладочной информации.