Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between class_eval, class_exec, module_eval and module_exec?

Tags:

ruby

I am reading the Module documentation but can't seem to understand their differences and which should be used where.

How is the eval different than exec?

like image 254
Kamilski81 Avatar asked Jan 29 '12 23:01

Kamilski81


People also ask

What is class_eval Ruby?

class_eval(array_second) adds the method second to any instance of Array by passing a String that will be evaluated in the context of the class Array . The call to String. class_eval with a block will evaluate the content of the block in the context of the class String .

What is class eval?

class_eval is a method of the Module class, meaning that the receiver will be a module or a class. The block you pass to class_eval is evaluated in the context of that class. Defining a method with the standard def keyword within a class defines an instance method, and that's exactly what happens here.


1 Answers

I'm going to answer a bit more than your question by including instance_{eval|exec} in your question.

All variations of {instance|module|class}_{eval|exec} change the current context, i.e. the value for self:

class Array   p self                     # prints "Array"   43.instance_eval{ p self } # prints "43" end 

Now for the differences. The eval versions accepts a string or a block, while the exec versions only accept a block but allow you to pass parameters to it:

def example(&block)   42.instance_exec("Hello", &block) end example{|mess| p mess, self } # Prints "Hello" then "42" 

The eval version does not allow to pass parameters. It provides self as the first parameter, although I can't think of a use for this.

Finally, module_{eval|exec} is the same as the corresponding class_{eval|exec}, but they are slightly different from instance_{eval|exec} as they change what is the current opened class (i.e. what will be affected by def) in different ways:

String.instance_eval{ def foo; end } Integer.class_eval  { def bar; end }  String.method_defined?(:foo)            # => false String.singleton_methods.include?(:foo) # => true Integer.method_defined?(:bar)           # => true 

So obj.instance_{eval|exec} opens the singleton class of obj, while mod.{class|module}_{eval|exec} opens mod itself.

Of course, instance_{eval|exec} are available on any Ruby object (including modules), while {class|module}_* are only available on Module (and thus Classes)

like image 87
Marc-André Lafortune Avatar answered Oct 13 '22 07:10

Marc-André Lafortune