13 March 2017

class_eval vs instance_eval

https://www.jimmycuadra.com/posts/metaprogramming-ruby-class-eval-and-instance-eval/

When called on a class name constant, these two methods will allow you to create methods of the opposite type from their names. MyClass.class_eval will create instance methods and MyClass.instance_eval will create class methods.

class Person
end

Person.class_eval do
  def say_hello
   "Hello!"
  end
end

jimmy = Person.new
jimmy.say_hello # "Hello!"


class Person
end

Person.instance_eval do
  def human?
    true
  end
end

Person.human? # true

http://web.stanford.edu/~ouster/cgi-bin/cs142-winter15/classEval.php

class_eval is equivalent to typing the code inside a class statement

MyClass.class_eval do
  def num
    @num
  end
end

behaves exactly the same as the following code:

class MyClass
  def num
    @num
  end
end

class_eval vs extend

Is this syntax functionally equivalent

def self.included(base)
  base.class_eval do
    extend ClassMethods
  end
end

to this?

def self.included(base)
  base.extend ClassMethods
end

Response:

The only relevant difference is that only classes respond to class_eval, whereas both classes and instances respond to extend.

If you don’t plan on using your method with object instances, then they are equivalent, though the second implementation can be used to add instance methods to a particular instance, while the first one cannot.

class_eval vs define_method

https://tenderlovemaking.com/2013/03/03/dynamic_method_definitions.html

Defining methods with define_method is faster, consumes less memory, and depending on your application isn’t significantly slower than using a class_eval defined method. So what is the down side?

Closures

The main down side is that define_method creates a closure. The closure could hold references to large objects, and those large objects will never be garbage collected.

When using define_method be careful not to hold references to objects you don’t care about.