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?
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!"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With