覆盖ActiveSupport :: Concern模块中的方法,这些方法由同一模块中的类方法定义

时间:2015-01-29 12:32:50

标签: ruby-on-rails ruby activesupport method-overriding activesupport-concern

我有一个ActiveSupport :: Concern模块,大致如下所示:

module MyModel
  module Acceptance

    extend ActiveSupport::Concern

    included do
      enum status: [:declined, :accepted]
    end

    def declined!
      self.status = :declined
      # some extra logic
      self.save!
    end

    def accepted!
      self.status = :accepted
      # some extra logic
      self.save!
    end
  end
end

这只会被包含在ActiveRecord类中,因此使用enum。基本上,我正在覆盖由declined!创建的accepted!ActiveRecord::Enum.enum方法以及我自己的一些额外的自定义逻辑。

问题是,这不起作用,因为当我致电@model.declined!时,它只会调用declined!的原始实现并忽略我的自定义方法。

看起来我的自定义方法被包含在调用类之前运行包含的块 - 这意味着我的自定义方法被enum定义的方法覆盖,而不是反过来说。

在这种特殊情况下有一些简单的解决方法(例如,我可以将调用enum移回包含类并确保它位于行include MyModel::Acceptance之上,但我想知道是否有办法我可以解决这个问题,同时将它保存在同一个模块中。

有没有办法可以在included中调用定义实例方法的类方法,然后在同一个Concern模块中覆盖该实例方法?

1 个答案:

答案 0 :(得分:8)

我认为你正在寻找define_method

module MyModel
  module Acceptance

    extend ActiveSupport::Concern

    included do
      enum status: [:declined, :accepted]

      define_method :declined! do
        self.status = :declined
        # some extra logic
        self.save!
      end

      define_method :accepted! do
        self.status = :accepted
        # some extra logic
        self.save!
      end

    end
  end
end