10

我有一个 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模块中覆盖该实例方法?

4

1 回答 1

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
于 2015-02-27T00:44:13.020 回答