【发布时间】:2017-04-26 20:33:10
【问题描述】:
我有 2 个通过多态关联链接的模型
class MyModel < ActiveRecord::Base
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings
def tags=(ids)
self.tags.delete_all
self.tags << Tag.where(id: ids)
end
end
class Tagging < ActiveRecord::Base
include PublishablePolymorphicRelationship
belongs_to :tag
belongs_to :taggable, :polymorphic => true
end
class Tag < ActiveRecord::Base
has_many :taggings
has_many :my_models, :through => :taggings, :source => :taggable, :source_type => 'MyModel'
end
tag1 = Tag.create!(...)
tag2 = Tag.create!(...)
my_model = MyModel.create!(...)
my_model.update!(tags: [tag1.id])
我创建了一个实现 after_update 挂钩的关注点,以便我可以在消息队列上发布更改
但是,当调用钩子时,更改哈希为空。以及关系
module PublishablePolymorphicRelationship
extend ActiveSupport::Concern
included do
after_update :publish_update
def publish_update
model = self.taggable
puts model.changes
puts self.changes
... # do some message queue publish code
end
end
结束 这将返回
{}
{}
有没有办法可以捕捉到多态关联的变化。
理想情况下,我不会在关注点中直接引用tags 模型,因为我希望这个关注点可用于其他模型。不过,我愿意使用关注点在模型中添加一些配置。
跟进问题:这样做是否正确?我很惊讶更新挂钩首先被调用。也许我应该对创建或删除挂钩采取行动?我愿意接受建议。
【问题讨论】:
-
首先摆脱 hacky
MyModel#tags=setter。通过使用 rails 为任何has_many关联创建的tags_ids=设置器,已经有更好的内置方法来执行此操作。它也可以与复选框助手一起使用。 -
另外,为了您的工作,您需要将
after_update :publish_update放在included do ... end块中。回调和关联是在模型的类定义中定义的。但我真的不明白你为什么要使用关注点,因为它似乎不太可重用。 -
为了简化示例,我在实践中使用
self.taggable对模型进行硬编码,我使用类方法来设置多态关系键并使用self.send(_polymorphic_key)这有意义吗?您认为这会提高可重用性吗? -
是的,这使它完全不同。您可能需要阅读 ActiveSupport::Concern 的文档,因为您需要记住,需要在类的上下文中评估的代码需要在模块包含在类中时运行 - 而不是在模块定义中。
-
这是一个很好的提醒(可能会为未来的读者服务)。幸运的是,我知道这一点。
标签: ruby-on-rails ruby-on-rails-4 activerecord polymorphic-associations