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