开发者

How do I use class_eval?

I don't understand class_eval.

class Module
  def attr_ (*syms)
    syms.each do |sym|
      class_eval %{def #{sym}= (val)
        @#{sym} = val
      开发者_运维百科end}
    end
  end
end

What does the % mean?

What does class_eval do?

And where is (val) coming from?


The short answer is: you probably want to avoid using class_eval like this.

Here's an explanation of your code:

The %{hello} is just another way to write a string literal in Ruby, without having to worry about escaping double or single quotes within the string:

%{hello "world"} == "hello \"world\""  # => true

The val in your code is an argument of the method being defined.

The class_eval is used to define some methods by computing the text one would write to do the definition and then evaluating it. It is not necessary here, BTW. An equivalent code would be:

class Module
  def attr_ (*syms)
    syms.each do |sym|
      define_method "#{sym}=" do |val|
        instance_variable_set "@#{sym}", val
      end
    end
  end
end

This is just equivalent to the builtin attr_writer.

Update: There can actually be a significant difference between the two...

The class_eval version is vulnerable if you can't trust the argument syms. For example:

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

The class_eval version will print "I can execute anything here" twice, proving it can execute anything. The define_method version won't print anything.

This type of code was pivotal to create major vulnerability for all installed Rails apps.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜