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

GMA*_*GMA 10 ruby overriding ruby-on-rails activesupport 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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Chi*_*hip 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
Run Code Online (Sandbox Code Playgroud)