ActiveRecord、has_many :through 和多态关联
Posted
技术标签:
【中文标题】ActiveRecord、has_many :through 和多态关联【英文标题】:ActiveRecord, has_many :through, and Polymorphic Associations 【发布时间】:2010-12-13 14:04:19 【问题描述】:伙计们,
想确保我理解正确。并且请忽略此处的继承情况(SentientBeing),而是尝试关注 has_many 中的多态模型:通过关系。也就是说,请考虑以下...
class Widget < ActiveRecord::Base
has_many :widget_groupings
has_many :people, :through => :widget_groupings, :source => :person, :conditions => "widget_groupings.grouper_type = 'Person'"
has_many :aliens, :through => :widget_groupings, :source => :alien, :conditions => "video_groupings.grouper_type = 'Alien'"
end
class Person < ActiveRecord::Base
has_many :widget_groupings, :as => grouper
has_many :widgets, :through => :widget_groupings
end
class Alien < ActiveRecord::Base
has_many :widget_groupings, :as => grouper
has_many :widgets, :through => :widget_groupings
end
class WidgetGrouping < ActiveRecord::Base
belongs_to :widget
belongs_to :grouper, :polymorphic => true
end
在一个完美的世界中,给定一个 Widget 和一个 Person,我想执行以下操作:
widget.people << my_person
但是,当我这样做时,我注意到 widget_groupings 中“grouper”的“type”始终为 null。但是,如果我像以下这样:
widget.widget_groupings << WidgetGrouping.new(:widget => self, :person => my_person)
然后一切都按我通常的预期工作。我认为我从未见过非多态关联会发生这种情况,只是想知道这是否是此用例特有的东西,或者我是否可能正在盯着一个错误。
感谢您的帮助!
【问题讨论】:
【参考方案1】:有很多 :through 和 polymorphic 不能一起工作。如果您尝试直接访问它们,它应该会引发错误。 如果我没记错的话,你必须手写widget.people和pushroutine。
我不认为这是一个错误,它只是尚未实现的东西。我想我们会在功能中看到它,因为每个人都有一个可以使用它的案例。
【讨论】:
他们确实一起工作。例如: has_many :subscriptions, :as => :subscribable has_many :subscribers, :through => :subscriptions, :source => :user 我将在不久的将来将我的失败代码示例作为单独的帖子提出:) 弄清楚如何绕过该错误将使我省去很多麻烦。【参考方案2】:Rails 3.1.1 中有一个known issue 破坏了这个功能。如果您遇到此问题,请先尝试升级,它已在 3.1.2 中修复
你离得太近了。问题是您滥用 :source 选项。 :source 应该指向多态的 belongs_to 关系。然后您需要做的就是为您要定义的关系指定 :source_type。
这个对 Widget 模型的修复应该可以让您完全按照您的要求进行操作。
class Widget < ActiveRecord::Base
has_many :widget_groupings
has_many :people, :through => :widget_groupings, :source => :grouper, :source_type => 'Person'
has_many :aliens, :through => :widget_groupings, :source => :grouper, :source_type => 'Alien'
end
【讨论】:
哦,天哪,这太明显了,我简直不敢相信我对它一无所知。谢谢 EmFi! 没问题,我想我第一次遇到这个问题时已经苦恼了大约一天。没有帮助,这是我在 Rails 中尝试做的第一件事,不涉及遵循教程/书籍。 正如 scotkf 所指出的,ActiveRecord 3.1.1 中有一个回归阻止了这种行为。升级到 3.1.2 将允许此解决方案工作。 与@Shtirlic 提到的相同。有没有办法不指定 source_type,所以你有一个混合的结果集?如果有人解决了这个问题,很想知道如何解决。 从 Rails 4.2.0 开始仍然有效。但是,现在有没有办法在没有 source_type 和两个单独的关联的情况下实现这一点?【参考方案3】:如上所述,由于 :source 上的错误,这不适用于 rails 3.1.1,但它已在 Rails 3.1.2 中修复
【讨论】:
以上是关于ActiveRecord、has_many :through 和多态关联的主要内容,如果未能解决你的问题,请参考以下文章
Rails ActiveRecord:三个表 has_many 通过:关联
Rails ActiveRecord 关联“has_many,每个都有 has_one”
如何使用has_many通过关系缩短三重连接ActiveRecord查询?
带有 has_many belongs_to 关联的 Rails activerecord 查询