Что означает class_eval << - "end_eval", __FILE__, __LINE__ в Ruby?
Я изучаю, как использовать 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__
ссылается на текущий файл, но что именно делает все это? Не знаю, как искать это:).
3 ответа
__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__ для добавления отладочной информации.
Отметим также, что eval
по возможности следует избегать цепочек В вашем конкретном случае замена #class_eval
с #class_exec
возможно и должно быть предпочтительным:
class_exec do
define_method block_accessor do |*args, &block|
unless args.empty? && block.nil?
args.push block if block_given?
instance_variable_set "@#{block_accessor}", [args].flatten
end
instance_variable_get "@#{block_accessor}"
end
end