从mixin添加关联而不覆盖现有关联

时间:2014-01-15 20:32:45

标签: ruby-on-rails ruby activerecord

我有很多类,如下所示:

class Event < ActiveRecord::Base
  include PreventUpdate

  has_many :participants, conditions: ...
  has_many :venues, conditions: ...
  has_many :companies, conditions: ...
end

我有一个模块处理类的prevent_update逻辑(obj过去,obj被禁止),并且作为其一部分,它查询include类的has_many关联,以便写入before_add挂钩到那些关联。 / p>

module PreventUpdate
  extend ::ActiveSupport::Concern

  included do 
    self.reflect_on_all_associations(:has_many).each do |assoc|
      has_many assoc.name, before_add: :prevent_update
    end
  end

  def prevent_update
    #core prevent update logic
  end

end

唯一的问题是动态添加的原始has_many语句会相互覆盖。哪个覆盖取决于包含模块的包含类的位置。

动态添加和原始声明是否可以“累积”,即模块的声明可以简单地添加到原始声明而不会覆盖?

1 个答案:

答案 0 :(得分:2)

这是未经测试的,但您应该可以这样做:

included do 
  self.reflect_on_all_associations(:has_many).each do |assoc|
    assoc.options.merge!(:before_add => :prevent_update)
  end
end

这需要在include声明之后关注has_many。如果您想在他们之前执行include,可以添加:

module ClassMethods
  def modify_associations
    self.reflect_on_all_associations(:has_many).each do |assoc|
      assoc.options.merge!(:before_add => :prevent_update)
    end
  end
end

然后:

# ...    
has_many :companies, conditions: ...
modify_associations

修改

这应该有效:

included do 
  self.reflect_on_all_associations(:has_many).each do |assoc|
    has_many assoc.name, assoc.options.merge(:before_add => :prevent_update)
  end
end