【问题标题】:Using ActiveSupport::Concern to overload a class method使用 ActiveSupport::Concern 重载类方法
【发布时间】:2014-04-28 02:20:34
【问题描述】:

我有一个类方法,我希望模块重载,这样模块方法可以调用 super 或其他方式来调用原始类的实现。这类似于 alias_method_chain,但问题是:是否可以通过 ActiveSupport::Concern 来实现?

考虑以下几点:

module CustomAction
  CUSTOM_ACTIONS = {custom_action_one: "c1", custom_action_two: "c2"}

  include ActiveSupport::Concern
  module ClassMethods
    def find(id)
      CUSTOM_ACTIONS[id] || super
    end
  end
end

class Action
  include CustomAction

  ACTIONS = {action_one: "1", action_two: "2"}

  def self.find(id)
     ACTIONS[id]
  end
end

因此,您可以在此处看到 CustomAction 类正在添加操作,并希望重载/覆盖默认的 #find 操作,以便它首先在自定义操作中查找,如果在那里找不到,则会回退到原始查找实现。

但是,这不起作用。将始终调用原始实现。即使您将 include 放在原始 #find 的定义之后也是如此。

我试图避免 alias_method_chain 因为 1) 它不是过时的吗?其中 ActiveSupport::Concern 是新的热点 2) 它需要将包含放在实现下方,这有点奇怪

想法?

【问题讨论】:

    标签: ruby-on-rails ruby design-patterns activesupport-concern


    【解决方案1】:

    您不能使用 ActiveSupport::Concern 覆盖类方法,因为 ActiveSupport::Concern 使用 (ActiveSupport::Concern source code):

    base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
    

    同理:

       class Action
          extend  CustomAction::ClassMethods
       end 
    

    所以,你应该使用 prepend ,在 Action single instance 之前插入 CustomAction::ClassMethods 。结果是:

    module CustomAction
      CUSTOM_ACTIONS = {custom_action_one: "c1", custom_action_two: "c2"}
    
      module ClassMethods
        def find(id)
          CUSTOM_ACTIONS[id] || super
        end
      end
    end
    
    class Action
    
      ACTIONS = {action_one: "1", action_two: "2"}
    
      def self.find(id)
         ACTIONS[id]
      end
    
      #prepend on the Action single instance , not on the instance
      class << self 
        prepend CustomAction::ClassMethods
      end  
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-26
      • 2014-01-26
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      • 2012-09-14
      • 2015-12-29
      • 1970-01-01
      相关资源
      最近更新 更多