如何覆盖rails模型关注中的class_method

and*_*ndy 3 ruby ruby-on-rails ruby-on-rails-4 activesupport-concern

如何重写模型关注点中定义的类方法?

\n\n

这有点棘手,因为您\xe2\x80\x99并没有真正覆盖类方法,对吗?因为它\xe2\x80\x99s使用了块中定义类方法的关注API class_methods

\n\n

所以说我有一个问题,看起来像这样:

\n\n
module MyConcern\n  extend ActiveSupport::Concern\n\n  class_methods do\n    def do_something\n       #some code\n    end\n  end\n\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

在模型中..我将如何重写该方法,以便我可以像使用继承时使用 super 那样调用它?所以在我的模型中我\xe2\x80\x99d喜欢去:

\n\n
def self.do_something\n  #call module do_something\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n

Pau*_*nti 5

如果您已经在定义的模型中添加了included ,那么您应该能够使用:MyConcernself.do_somethingsuper

module MyConcern
  extend ActiveSupport::Concern

  class_methods do
    def do_something
      puts "I'm do_something in the concern"
    end
  end
end

class UsesMyConcern < ActiveRecord::Base
  include MyConcern

  def self.do_something
    super
  end
end

UsesMyConcern.do_something
# => "I'm do_something in the concern"
Run Code Online (Sandbox Code Playgroud)

如果您还没有或不想include MyConcern在模型中使用,并且希望do_something在不创建任何中间对象的情况下调用模块,则可以将模型更改为:

class UsesMyConcern < ActiveRecord::Base
  def self.do_something                
    MyConcern::ClassMethods.instance_method(:do_something).bind(self).call
  end
end

UsesMyConcern.do_something
# => "I'm do_something in the concern"
Run Code Online (Sandbox Code Playgroud)

ActiveSupport::Concern.class_methodsClassMethods如果关注点中还没有模块,则定义一个模块,这就是我们可以找到该do_something方法的地方。