我对文档中ActiveSupport :: Concern的this示例感到有些困惑:
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
。 base
指的是对象,无论它是类对象还是对象实例。 extend
上的base
会将模块中的方法包含在base
上作为单例方法。 include
会将方法添加到类对象的实例中。
但是,class_eval还用于将实例方法添加到类对象的实例中。然而,scope
是一种类方法:
添加用于检索和查询对象的类方法。
由于scope
是一种类方法,为什么该示例使用class_eval
而不是instance_eval
?
答案 0 :(得分:1)
class_eval
比instance_eval
更强大。
使用class eval,您可以评估类的 context 中的代码,允许您定义和调用类方法,实例方法等:
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
使用目标实例作为接收器来评估代码,因此如果您尝试定义实例方法,则必须更加狡猾:
Greeter = Class.new
Greeter.instance_eval do
def friendly?
true
end
define_method(:say_hi) { "Howdy!" }
end
donato = Greeter.new
donato.say_hi # => "Howdy!"