This presentation is an introduction to Ruby eval. It also talks about instance_eval and class_eval methods and lists a meta programming example using eval at the end of the presentation.
2. Binding and eval
If ruby program can generate a string of valid ruby code, the Kernel.eval
method can evaluate the code.
A Binding object represents the state of Ruby’s variable bindings at some
moment.
The Kernel.binding (private method) returns the bindings in effect at the
location of the call.
Binding object is second argument to eval and the string you specify will be
evaluated in the context of those bindings.
3. eval
eval only takes a string to evaluate. eval will evaluate the string in the current
context or if a binding is given.
def getBinding(str) # returns the current context of the value of str
return binding
end
str = "hello"
eval "str + ' Fred'" #=> "hello Fred"
eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
4. If we define an instance method that returns a Binding object that represents
the variable bindings inside an object,
class Object
def bindings
binding
end
end
class A
def initialize(x)
@x = x
end
end
a = A.new(5)
eval(“@x”, a.bindings) #=> 5
5. class_eval and instance_eval
class A; end
class A
A.class_eval do def hello_1
def hello_1 p ‘hello_1’
p 'hello_1' end
end end
end
A.hello_1 #=> undefined method `hello' for A:Class (NoMethodError)
A.new.hello_1 #=> “hello”
6. A.instance_eval do
def hello_2
p 'hello_2'
end
end
A.hello_2 #=> "hello_2"
A.new.hello_2 #=> undefined method `hello_2' for #<A:0x32d05fc> (NoMethodError)
7. a = A.new
a.instance_eval do
def hello_3
p 'hello_3'
end
end
a.hello_3 #=> "hello_3"
b = A.new
b.hello_3 #=> undefined method `hello_3' for #<A:0x32d019c> (NoMethodError)
8. instance_eval => Object class
module_eval (synonym for class_eval) => Module class
They evaluate the code in the context of the specified object, i.e. value of self
while code is being evaluated.
# Returns value of a’s instance variable @x
a.instance_eval(“@x”)
# Define an instance method len of String
String.class_eval(“def len; size; end”)
# The quoted code behaves just as if it was inside class String and end
String.class_eval("alias len size")
class_eval is a function that can ONLY be called by class as the name
suggests.
9. # Use instance_eval to define class method String.empty
String.instance_eval(“def empty; ‘ ’ ; end”)
instance_eval defines singleton methods of the object (& this results in class
method when it is called on a class object)
class_eval defines regular instance methods.
They can accept a block of code to evaluate. Eval can not.
a.instance_eval {@x}
String.class_eval {
def len
size
end
end
Ruby 1.9 :- instance_exec and class_exec
They can accept arguments as well and pass them to block
10. class A
has_attribute :my_attribute, :another_attribute
end
a = A.new
puts a.methods - Object.methods
# => ["my_attribute", my_attribute=", "another_attribute", "another_attribute="]
a.my_attribute = 1
a.my_attribute # => 1
a.another_attribute = "A String"
a.another_attribute # => "A String"
11. Object.instance_eval do
def has_attribute( *attrs )
attrs.each do | attr |
self.class_eval %Q{
def #{attr}=(val)
instance_variable_set("@#{attr}", val)
end
def #{attr}
instance_variable_get("@#{attr}")
end
}
end
end
end