我如何使用class_eval?

nev*_*ame 20 ruby metaprogramming

我不明白class_eval.

class Module
  def attr_ (*syms)
    syms.each do |sym|
      class_eval %{def #{sym}= (val)
        @#{sym} = val
      end}
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

什么%意思?

怎么class_eval办?

哪里(val)来了?

Mar*_*une 26

简短的回答是:你可能想避免class_eval像这样使用.

这是您的代码的解释:

%{hello}只是在Ruby中编写字符串文字的另一种方法,而不必担心在字符串中转义双引号或单引号:

%{hello "world"} == "hello \"world\""  # => true
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

这相当于内置attr_writer.

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

class_eval如果你不相信这个论点,那么该版本很容易受到攻击syms.例如:

class Foo
  attr_ "x; end; puts 'I can execute anything here!'; val=42; begin; val"
end
Run Code Online (Sandbox Code Playgroud)

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

此类代码对于为所有已安装的Rails应用程序创建主要漏洞至关重要.

  • 在此上下文中,执行一些指令.如果你要"评估"表达式6 + 5,它就是11. (4认同)