为 has_many 或 habtm 动态创建 after_add 和 after_remove 回调?

发布于 2024-12-29 02:16:14 字数 1475 浏览 0 评论 0原文

有没有办法将 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< /code> 只是一个类方法。

Is there a way to dynamically add after_add and after_remove callbacks to an existing has_many or has_and_belongs_to_many relationship?

For example, suppose I have models User, Thing, and a join model UserThingRelationship, and the User model is something like this:

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

I'd like to be able to, in a module that extends User, add :after_add and :after_remove callbacks to the User.has_many(:things, ...) relationship. I.e., have something like

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

So that

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

Is effectively the same as

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

This can be done pretty effectively for adding after_save, etc, callbacks to the model that's being extended, since ActiveRecord::Base#after_save is just a class method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忘年祭陌 2025-01-05 02:16:14

最简单的是

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

注意:在 Rails 7 中不再有效(感谢 Andrew Hodgkinson 指出了这一点)

The easiest would be

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

Note: No longer works in Rails 7 (thanks to Andrew Hodgkinson for pointing this out)

青巷忧颜 2025-01-05 02:16:14

我能够通过使用 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

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

I was able to come up with the following by using 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

I don't want to answer my own question, so I won't give myself answer credit if someone else can come up with a better solution in the next few days.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文