Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails scope defined in a class_eval block or instance_eval block?

I am a little confused by this example on ActiveSupport::Concern from the documentation:

module M
  def self.included(base)
    base.extend ClassMethods
    base.class_eval do
      scope :disabled, -> { where(disabled: true) }
    end
  end

  module ClassMethods
    ...
  end
end

self.included in a Module is called when you include or extend the Module in a Class. base refers to the object, whether it is a class object or object instance. extend on base will include the methods in Module as singleton methods on base. include will add the methods to the class object's instances.

However, class_eval also is used to add instance methods to a class object's instances. Yet, scope is a class method:

Adds a class method for retrieving and querying objects.

Since scope is a class method, why is the example using class_eval rather than instance_eval?

like image 451
Daniel Viglione Avatar asked Mar 03 '26 02:03

Daniel Viglione


1 Answers

class_eval is more powerful than instance_eval.

With class eval, you can evaluate code in the context of the class, allowing you to define and call class methods, instance methods, and more:

Greeter = Class.new

Greeter.class_eval do
  def self.friendly?
    true
  end

  def say_hi
   "Howdy!"
  end
end

donato = Greeter.new
donato.say_hi # => "Howdy!"
Greeter.friendly? # => true

instance_eval instead evaluates code with the target instance as the receiver, so you'd have to be a bit more crafty if you're trying to define instance methods:

Greeter = Class.new

Greeter.instance_eval do
  def friendly?
    true
  end

  define_method(:say_hi) { "Howdy!" }
end

donato = Greeter.new
donato.say_hi # => "Howdy!"
like image 101
fny Avatar answered Mar 04 '26 16:03

fny



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!