Краткий ответ: вы, вероятно, хотите избегать , используя class_eval
, как это.
Вот объяснение вашего кода:
%{hello}
- это просто еще один способ написать строковый литерал в Ruby, не беспокоясь о экранировании двойных или одинарных кавычек в строке:
%{hello "world"} == "hello \"world\"" # => true
val
в вашем коде является аргументом определяемого метода.
class_eval
используется для определения некоторых методов путем вычисления текста, который можно написать для определения, а затем его оценки. Это не обязательно здесь, кстати. Эквивалентный код будет:
class Module
def attr_ (*syms)
syms.each do |sym|
define_method "#{sym}=" do |val|
instance_variable_set "@#{sym}", val
end
end
end
end
Это просто эквивалентно встроенному attr_writer
.
Обновление : На самом деле между этими двумя понятиями может быть существенная разница ...
Версия class_eval
уязвима, если вы не можете доверять аргументу syms
. Например:
class Foo
attr_ "x; end; puts 'I can execute anything here!'; val=42; begin; val"
end
Версия class_eval
напечатает «Я могу выполнить все что угодно» дважды, доказывая, что она может выполнить что угодно. Версия define_method
ничего не печатает.
Этот тип кода был ключевым для создания серьезной уязвимости для всех установленных приложений Rails.