Как использовать class_eval?

Я не понимаю 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)?


person never_had_a_name    schedule 09.06.2010    source источник
comment
Я скопировал ваш pastebin напрямую (и исправил запись). Я полагаю, что последний } неуместен; он должен быть после val, а не после end   -  person Marc-André Lafortune    schedule 09.06.2010
comment
Не следует оставлять пробел между идентификатором метода и последующими скобками. Руби предупредит вас, когда вы это сделаете.   -  person Rein Henrichs    schedule 17.04.2011


Ответы (1)


Короткий ответ: вы, вероятно, захотите избегать использования 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.

person Marc-André Lafortune    schedule 09.06.2010
comment
что означает слово оценивать? я не понимаю этого слова. - person never_had_a_name; 09.06.2010
comment
В этом контексте выполните некоторые инструкции. Если бы вы оценили выражение 6 + 5, это 11. - person ALW; 10.06.2010