如何覆盖模型关注中定义的类方法?
这有点棘手,因为你没有真正重写类方法吗?因为它使用了class_methods
块中定义类方法的关注api。
所以说我有一个看起来像这样的问题:
module MyConcern
extend ActiveSupport::Concern
class_methods do
def do_something
#some code
end
end
end
在模型中..我将如何覆盖该方法,以便我可以像使用继承时使用super一样调用它?所以在我的模型中,我想去:
def self.do_something
#call module do_something
end
答案 0 :(得分:2)
如果您在定义include
的模型中MyConcern
d self.do_something
,那么您应该能够使用super
:
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"
如果您没有或不想在模型中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"
ActiveSupport::Concern.class_methods
在关注点中定义ClassMethods
模块,如果还没有,那么我们可以找到do_something
方法。
答案 1 :(得分:1)
为什么不简单地调用模块的方法:MyConcern.do_something
?
我不确定模块是否容易super
(虽然我可以看到为什么这可能有用)。
下一个最佳解决方案可能是调用#included_modules
并手动迭代#responds_to?
:
def self.do_something
self.super_module(__method__)
end
def self.super_module(method)
self.included_modules.find { |m| m.responds_to? method }.public_send(method)
end
答案 2 :(得分:0)
使用alias_method_chain
的旧方式:https://ernie.io/2011/02/03/when-to-use-alias_method_chain/
新方法(需要&gt; ruby 2.0.0)你真的应该使用它,因为在rails 5.0中使用它时会有DEPRECATION WARNING: http://paweljaniak.co.za/2014/09/30/understanding-ruby-module-prepend-and-include/