1

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

如果类中缺少特定方法,我正在尝试向类动态添加一个空的 Rails 范围

该文档特别似乎表明这应该是可能的: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 已正确设置为此处的类,但是尝试评估作用域的创建失败,undefined method 'scope' for #<Class:0x0000560e35d2eb48>但是当我调用时,klass.ancestors我可以确认 klass 是继承自ActiveRecord::Base并且应该具有作用域。

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

4

1 回答 1

1

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

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

所以这Person.class不会返回ActiveRecord::Base但是Class:Person(上面的垂直链),这意味着你的代码kclass = class << self; self; end实际上返回Person.class的是Class:Person- 一个与 ActiveRecord::Base 没有任何相关的 Class 对象 - 所以它不会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.

于 2021-08-26T04:09:45.900 回答