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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With