Connecting Tech Pros Worldwide Help | Site Map

Metaprogramming in Ruby: class_eval vs. instance_eval

Newbie
 
Join Date: Nov 2006
Location: Seattle
Posts: 16
#1: Sep 7 '08
I'm using Ruby 1.8.6 btw.

For the longest time today (it seems) I've been trying to understand exactly the operating difference between class_eval and instance_eval. There are some obvious differences I'm perfectly aware of (e.g. class_eval is only on Class objects), but the reality is that some irb tinkering has left me more confused than ever. Given the following:

Expand|Select|Wrap|Line Numbers
  1. class Foo
  2.   # could be any class
  3. end
  4.  
  5. f = Foo.new
  6.  
  7. # Try out instance eval on f's class (Foo)
  8. f.class.instance_eval do
  9.   define_method :made_by_inst_eval do
  10.     puts "This method was made by calling instance_eval"
  11.     puts "Current 'self': #{self}"
  12.     puts "Current class of 'self': #{self.class}"
  13.   end
  14. end
  15.  
  16. f.made_by_inst_eval
  17.  
Gives me this:

Expand|Select|Wrap|Line Numbers
  1. This method was made by calling instance_eval
  2. Current 'self': #<Foo:0x8f098>
  3. Current class of 'self': Foo
If I then try doing the exact same thing with class_eval instead:

Expand|Select|Wrap|Line Numbers
  1. f.class.class_eval do
  2.   define_method :made_with_class_eval do
  3.     puts "This method was made by calling class_eval"
  4.     puts "Current 'self': #{self}"
  5.     puts "Current class of 'self': #{self.class}"
  6.   end
  7. end
  8.  
  9. f.made_with_class_eval
  10.  
I then get the same damn result:

Expand|Select|Wrap|Line Numbers
  1. This method was made by calling class_eval
  2. Current 'self': #<Foo:0x8ec88>
  3. Current class of 'self': Foo
  4.  
So, what's the difference between these two calls? In this particular situation? In general?

Some clear thoughts would be ever so appreciated!
Expert
 
Join Date: May 2007
Posts: 213
#2: Sep 8 '08

re: Metaprogramming in Ruby: class_eval vs. instance_eval


There may not be much of a difference in this situation, since both times it is being called on f.class. I think the difference between the two is the receiver of where the method is defined, and thus what it applies to. This page may provide a little extra info around example 5.
Reply