【问题标题】:Overriding methods in an ActiveSupport::Concern module which are defined by a class method in the same module覆盖 ActiveSupport::Concern 模块中由同一模块中的类方法定义的方法
【发布时间】:2015-03-28 16:31:05
【问题描述】:

我有一个 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。基本上,我用我自己的一些额外的自定义逻辑覆盖了由ActiveRecord::Enum.enum 创建的declined!accepted! 方法。

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

看起来我的自定义方法被包含在调用类中之前包含的块正在运行 - 这意味着我的自定义方法被enum定义的那些覆盖,而不是其他一路走来。

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

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

【问题讨论】:

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


    【解决方案1】:

    我想你正在寻找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
    

    【讨论】:

    • 您能否详细说明为什么会这样?在 Rails 3.2 中,@GeorgeMillo 的方式效果很好。在 Rails 4.2 中它没有。他们是否在内部更改了有关方法添加方式的某些内容?
    • 我刚刚重新阅读了这个问题,那里有一种解释。但任何额外的信息将不胜感激:)
    猜你喜欢
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 2013-09-05
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    相关资源
    最近更新 更多