【问题标题】:How to override class_method in rails model concern如何在rails模型关注中覆盖class_method
【发布时间】:2016-07-21 13:52:40
【问题描述】:

如何覆盖模型关注点中定义的类方法?

这有点棘手,因为您并没有真正覆盖类方法,对吧?因为它使用了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

?

【问题讨论】:

  • 您找到解决方案了吗?

标签: ruby-on-rails ruby ruby-on-rails-4 activesupport-concern


【解决方案1】:

如果你在定义self.do_something的模型中有included MyConcern,你应该可以使用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 方法。

【讨论】:

    【解决方案2】:

    为什么不简单地调用模块的方法: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
    

    【讨论】:

      【解决方案3】:

      使用alias_method_chain的旧方式:https://ernie.io/2011/02/03/when-to-use-alias_method_chain/

      新方法(需要> ruby​​ 2.0.0)你真的应该使用它,因为在rails 5.0中使用它时会有一个弃用警告: http://paweljaniak.co.za/2014/09/30/understanding-ruby-module-prepend-and-include/

      【讨论】:

      • @reven 这是一个很酷的帖子,实际上真的很有用......但没有回答问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多