使用ActiveSupport :: Concern重载类方法

时间:2014-03-20 22:29:15

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

我有一个类方法,我希望模块重载,这样模块方法可以调用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操作,以便它首先在自定义操作中查找,如果它在那里找不到,则会回退到原始查找实施。

然而,这不起作用。始终会调用原始实现。即使您在原始#find。

的定义之后添加了include,也是如此

我试图避免使用alias_method_chain,因为1)是不是已经过时了?哪里ActiveSupport :: Concern是新的热点2)它需要在实现下面放置包含有点奇怪

思想?

1 个答案:

答案 0 :(得分:0)

您不能使用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单个实例之前插入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