在class_eval块或instance_eval块中定义的Rails范围?

时间:2016-12-20 18:12:50

标签: ruby-on-rails ruby

我对文档中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.includedbase指的是对象,无论它是类对象还是对象实例。 extend上的base会将模块中的方法包含在base上作为单例方法。 include会将方法添加到类对象的实例中。

但是,class_eval还用于将实例方法添加到类对象的实例中。然而,scope是一种类方法:

  

添加用于检索和查询对象的类方法。

由于scope是一种类方法,为什么该示例使用class_eval而不是instance_eval

1 个答案:

答案 0 :(得分:1)

class_evalinstance_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!"