【问题标题】:Dynamically create after_add and after_remove callbacks for has_many or habtm?为 has_many 或 habtm 动态创建 after_add 和 after_remove 回调?
【发布时间】:2012-02-17 05:29:18
【问题描述】:

有没有办法将after_addafter_remove 回调动态添加到现有的has_manyhas_and_belongs_to_many 关系中?

例如,假设我有模型UserThing 和一个连接模型UserThingRelationship,而User 模型是这样的:

class User < ActiveRecord::Base
  has_many :user_thing_relationships
  has_many :things, :through => :user_thing_relationships
end

我希望能够在扩展User 的模块中,将:after_add:after_remove 回调添加到User.has_many(:things, ...) 关系。即,有类似的东西

module DoesAwesomeStuff
  def does_awesome_stuff relationship, callback
    # or however this can be achieved...
    after_add(relationship) callback
    after_remove(relationship) callback
  end
end

这样

class User < ActiveRecord::Base
  has_many :user_thing_relationships
  has_many :things, :through => :user_thing_relationships

  does_awesome_stuff :things, :my_callback
  def my_callback; puts "awesome"; end
end

实际上与

相同
class User < ActiveRecord::Base
  has_many :user_thing_relationships
  has_many :things, :through => :user_thing_relationships, :after_add => :my_callback, :after_remove => :my_callback

  def my_callback; puts "awesome"; end
end

这可以非常有效地为正在扩展的模型添加after_save 等回调,因为ActiveRecord::Base#after_save 只是一个类方法。

【问题讨论】:

    标签: ruby-on-rails activerecord callback has-many-through


    【解决方案1】:

    最简单的应该是

    User.after_add_for_things << lambda do |user, thing| 
      Rails.logger.info "#{thing} added to #{user}"
    end
    

    【讨论】:

    【解决方案2】:

    我能够通过使用ActiveRecord::Reflection 提出以下建议:

    module AfterAdd
      def after_add rel, callback
        a = reflect_on_association(rel)
        send(a.macro, rel, a.options.merge(:after_add => callback))
      end
    end
    
    class User < ActiveRecord::Base
      extend AfterAdd
    
      has_many :user_thing_relationships
      has_many :things, :through => :user_thing_relationships
    
      after_add :things, :my_callback
    
      def my_callback
        puts "Hello"
      end
    end
    

    我不想回答我自己的问题,所以如果其他人在接下来的几天内能提出更好的解决方案,我不会给自己的答案。

    【讨论】:

    • 很抱歉把这个埋了,但是 afaik,你的回调会泄露,不是吗? IE。如果两个线程同时运行after_add,你不知道哪个回调有效?
    • 你的方法有个缺点。如果是has_and_belongs_to_many 关联,您将调用has_and_belongs_to_many 两次,这将为user_thing_relationships 定义一个额外的dependent: :delete
    猜你喜欢
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    相关资源
    最近更新 更多