How do I use class_eval?

后端 未结 1 1921
[愿得一人]
[愿得一人] 2020-12-30 00:58

I don\'t understand class_eval.

class Module
  def attr_ (*syms)
    syms.each do |sym|
      class_eval %{def #{sym}= (val)
        @#{sym} = v         


        
相关标签:
1条回答
  • 2020-12-30 01:28

    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 讨论(0)
提交回复
热议问题