我如何使用class_eval?

时间:2010-06-09 05:44:30

标签: ruby metaprogramming

我不明白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)来自哪里?

1 个答案:

答案 0 :(得分:26)

简短的回答是:您可能希望避免使用此类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

更新:两者之间实际上可能存在显着差异......

如果您不信任参数class_eval,则syms版本容易受到攻击。例如:

class Foo
  attr_ "x; end; puts 'I can execute anything here!'; val=42; begin; val"
end

class_eval版本将打印“我可以在这里执行任何操作”两次,证明它可以执行任何操作。 define_method版本不会打印任何内容。

type of code对于为所有已安装的Rails应用创建major vulnerability至关重要。