为什么这个继承自 ActiveRecord::Base 的 class 不能 class_eval 作用域

Why is this class which inherits from ActiveRecord::Base incapable of class_eval ing scope

注意:我知道我在这里做的事情可能很愚蠢,但我什至不一定要使用这段代码我现在只是好奇。

如果 class

上缺少特定方法,我正在尝试将一个空的 Rails 作用域动态添加到 class

这份文件似乎特别表明这应该是可能的:https://api.rubyonrails.org/classes/ActiveSupport/Concern.html

module Mod
  extend ActiveSupport::Concern

  class_methods do
    def method_missing(m, *args, &block)
      if m.match? /method/
        klass = class << self; self; end

        klass.class_eval { scope :method, -> {} }
      end
    end
  end
end

klass 在这里正确设置为 class 但是尝试评估范围的创建失败 undefined method 'scope' for #<Class:0x0000560e35d2eb48> 但是当我调用 klass.ancestors 我可以确认 klass 继承自ActiveRecord::Base 并且应该有作用域。

为什么我不能在这里 class_eval scope 的任何想法

假设有一个 class Person < ActiveRecord::Base 将包含您的模块 Mod。 在 Ruby 中,继承层次结构如下所示(水平超 class 链):

  Class                   Class
    |                       |
  Person -superclass->  ActiveRecord::Base

所以 Person.class 不会 return ActiveRecord::Base 而是 Class:Person (上面的垂直链),这意味着你的代码 kclass = class << self; self; end 实际上 return Person.classClass:Person - 一个 Class 对象,与 ActiveRecord::Base 没有任何关系 - 所以它不会 respond_to? :scope

module Mod
  extend ActiveSupport::Concern

  class_methods do
    # override Person#method_missing
    def method_missing(m, *args, &block)
      # anytime call Person.a_method_that_not_be_defined
      puts self # Person
      kclass = class << self; self; end # <--- Class:Person

所以在这种情况下,您应该使用 self.class_eval 而不是 kclass.class_eval