ActiveRecord,has_many:through和Polymorphic Associations

时间:2009-11-05 20:12:58

标签: ruby-on-rails activerecord polymorphic-associations

民间,

想确保我理解正确。请忽略继承的情况(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.people << my_person

但是,当我这样做时,我注意到'grouper'的'type'在widget_groupings中始终为null。但是,如果我喜欢以下内容:

widget.widget_groupings << WidgetGrouping.new({:widget => self, :person => my_person}) 

然后一切正常,正如我通常预期的那样。我不认为我曾经见过这种非多态关联,只是想知道这是否是这个用例的特定内容,或者我是否有可能盯着一个bug。

感谢您的帮助!

3 个答案:

答案 0 :(得分:160)

有一个带有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

答案 1 :(得分:3)

如上所述,由于以下错误:源代码,这不适用于rails 3.1.1,但它在Rails 3.1.2中修复了

答案 2 :(得分:-4)

有很多:通过和多态不能一起工作。如果您尝试直接访问它们,则应该抛出错误。 如果我没有弄错的话,你必须亲自编写widget.people和推送例程。

我不认为这是一个错误,它只是尚未实现的东西。我想我们会在功能中看到它,因为每个人都有一个可以使用它的情况。