1

I'm confused as to when I should be using instance_eval and class eval.

I should or shouldn't use them?

Answer with simple examples on how to use them.

Thanks a lot.

1
  • I strongly recommend "Metaprogramming Ruby 2" by Paolo Perotta - it would answer these question in depth (along with many related ones that you didn't ask yet :)) and in general would give you a solid understanding of the Ruby object model (you really must understand the latter to work with Ruby, and there is way more here than the difference between numerous eval-like methods). Commented Dec 22, 2022 at 13:34

3 Answers 3

3

The class_eval and instance_eval are both used to reopen an object and define additional behaviour.

They follows the open/closed principle.

class_eval

class_eval is used to define additional behaviour in the context of a class.

Let's use the following Person class:

class Person
  def initialize(name)
    @name = name
  end
end

Person.class_eval do
  def say_hello
    puts "Hello! I'm #{@name}"
  end
end

j = Person.new "John"
j.say_hello # Hello! I'm John

r = Person.new "Robert"
r.say_hello # Hello! I'm Robert

Both j and p can use a new method called say_hello that wasn't defined in the definition of the class Person, but on an extension of it.

instance_eval

instance_eval is used to define additional behavior in the context of a receiving object.

The previous example could be rewritten as:

class Person
  def initialize(name)
    @name = name
  end
end

j = Person.new "John"

j.instance_eval do
  def say_hello
    puts "Hello! I'm #{@name}"
  end
end

j.say_hello # Hello! I'm John

Since we used instance_eval on j, only the behavior of j has been redefined, in fact we can't use say_hello on another instance:

r = Person.new "Robert"
r.say_hello # undefined method `say_hello' for #<Person:0x00007fac43c15b28 @name="Robert"> (NoMethodError)

This is the opposite of class_eval.

Summary

  • class_eval allows you to open and redefine the behavior of a class in order to extend all instances of the class
  • instance_eval allows you to open and redefine the behavior of just an instance of a class

You should or shouldn't use them?

I'm of the idea that you shouldn't use them, because this can lead to code fragmentation.

But you have to use them when you want to add behavior on third parties code or when you want to add behavior dynamically.

Sign up to request clarification or add additional context in comments.

8 Comments

"They follows the open/closed principle" – they obviously allow a class / object to be opened, but what about the "closed for modification" part?
@Stefan in order to extend the behavior you don't need to source code of a class. The source code is then "closed".
@Stefan, I've always been dissatisfied with the concept of "opening" a class or another object, as (to my knowledge) there is no mention of that in the Ruby documentation. We may share a general idea of what is meant by "opening" but I would prefer a more precise statement of the procedure.
@CarySwoveland the docs for Modules use the term "open" / "reopen" several times.
@Nullndr I find statements like "class_eval allows you to open and redefine the behavior of a class in order to extend all instances of the class" a bit misleading. One can (re)define the receiver's behavior using these methods, but this is not always the case. The receiver might be used as just a blank slate sandbox, as a throw-away execution context for some dynamic code (simply to isolate the dynamic code from the rest of the app and reduce the blast radius when things go wrong)
|
0

Use ClassName.instance_eval to define a class method (one associated with the class object but not visible to instances). Use ClassName.class_eval to define an instance method (one that applies to all of the instances of ClassName).

Comments

0

Source: RubyMonk

instance_eval

One of the major differences between eval and instance_eval is that with instance_eval you have the choice of explicitly handling the context of self. As instance_eval is a method on Object it is scoped by the object you specify.

class_eval

class_eval is much simpler than instance_eval which works on metaclasses (or the singleton object). It works on the class as if you were opening it in a text editor and adding new state or behaviour to it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.