ActiveRecord、has_many :through 和多态关联

发布于 2024-08-09 16:21:32 字数 1277 浏览 7 评论 0原文

伙计们,

想确保我正确理解这一点。并且请忽略这里继承的情况(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

但是,当我这样做时,我注意到了“石斑鱼”的“类型” ' 在 widget_groupings 中始终为空。但是,如果我执行以下操作:

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

那么一切都会按我通常的预期进行。我认为我从未见过这种情况发生在非多态关联中,只是想知道这是否是该用例特有的,或者我是否可能正在关注一个错误。

感谢您的帮助!

Folks,

Want to make sure I understand this correctly. And please disregard the case for inheritance here (SentientBeing), trying to instead focus on polymorphic models in has_many :through relationships. That said, consider the following...

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

In a perfect world, I'd like to, given a Widget and a Person, do something like:

widget.people << my_person

However, when I do this, I've noticed the 'type' of the 'grouper' is always null in widget_groupings. However, if I to something like the following:

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

Then all works as I would have normally expected. I don't think I've ever seen this occur with non polymorphic associations and just wanted to know if this was something specific to this use case or if I'm potentially staring at a bug.

Thanks for any help!

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

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

发布评论

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

评论(4

寄与心 2024-08-16 16:21:32

Rails 3.1.1 存在一个已知问题,该问题会破坏此功能。如果您遇到此问题,请先尝试升级,该问题已在 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

There is a known issue with Rails 3.1.1 that breaks this functionality. If you are having this problem first try upgrading, it's been fixed in 3.1.2

You're so close. The problem is you're misusing the :source option. :source should points to the polymorphic belongs_to relationship. Then all you need to do is specify :source_type for the relationship you're trying to define.

This fix to the Widget model should allow you do exactly what you're looking for.

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
余罪 2024-08-16 16:21:32

如上所述,由于 :source 上的错误,这不适用于 Rails 3.1.1,但在 Rails 3.1.2 中已修复

As mentioned above, this doesn't work with rails 3.1.1 due to a bug on :source, but it's fixed in Rails 3.1.2

清欢 2024-08-16 16:21:32

例如:位置有许多火车直升机卡车轮船火车直升机卡车轮船有许多位置

不同的位置可以有类似的传输(存储在可移动的多态列中)。

#db/migrations/create_moveable_locations.rb

class CreateMoveableLocations < ActiveRecord::Migration
  def change
    create_table :moveable_locations do |t|
      t.references :moveable, polymorphic: true
      t.references :location

      t.timestamps
    end
  end
end

#app/models/moveable_location.rb

class MoveableLocation < ActiveRecord::Base
  belongs_to :moveable, polymorphic: true
  belongs_to :location
end

#app/models/location.rb

class Location < ActiveRecord::Base
  has_many :moveable_locations, dependent: :destroy

  has_many :trains, through: :moveable_locations, source: :moveable, source_type: 'Train'
  has_many :copters, through: :moveable_locations, source: :moveable, source_type: 'Copter'
  has_many :trucks, through: :moveable_locations, source: :moveable, source_type: 'Truck'
  has_many :ships, through: :moveable_locations, source: :moveable, source_type: 'Ship'
end

#app/models/train.rb

class Train < ActiveRecord::Base
  has_many :moveable_locations, as: :moveable, dependent: :destroy
  has_many :locations, through: :moveable_locations
end

#app/models/copter.rb

class Copter < ActiveRecord::Base
  has_many :moveable_locations, as: :moveable, dependent: :destroy
  has_many :locations, through: :moveable_locations
end

#app/models/truck.rb

class Truck < ActiveRecord::Base
  has_many :moveable_locations, as: :moveable, dependent: :destroy
  has_many :locations, through: :moveable_locations
end

#app/models/ship.rb

class Ship < ActiveRecord::Base
  has_many :moveable_locations, as: :moveable, dependent: :destroy
  has_many :locations, through: :moveable_locations
end

使用:

train1 = Train.create(title: 'Train1')
train2 = Train.create(title: 'Train2')
location1 = Location.create(title: 'Location1', train_ids: [train1.id, train2.id])
location2 = Location.create(title: 'Location2', trains: [train1, train2])
location3 = Location.create(title: 'Location3')
location3.train_ids << [train1., train2.id]
location4 = Location.create(title: 'Location34')
location4.trains << [train1, train2]
copter1 = Copter.create(title: 'Copter1', location_ids: [location1.id, location2.id]
copter2 = Copter.create(title: 'Copter1')
copter2.location_ids << [location1.id, location2.id, location3.id]

For example: locations have many trains, copters, trucks, ships. And trains, copters, trucks, ships have many locations.

Different locations can have similar transports(store in moveable polymorphic columns).

#db/migrations/create_moveable_locations.rb

class CreateMoveableLocations < ActiveRecord::Migration
  def change
    create_table :moveable_locations do |t|
      t.references :moveable, polymorphic: true
      t.references :location

      t.timestamps
    end
  end
end

#app/models/moveable_location.rb

class MoveableLocation < ActiveRecord::Base
  belongs_to :moveable, polymorphic: true
  belongs_to :location
end

#app/models/location.rb

class Location < ActiveRecord::Base
  has_many :moveable_locations, dependent: :destroy

  has_many :trains, through: :moveable_locations, source: :moveable, source_type: 'Train'
  has_many :copters, through: :moveable_locations, source: :moveable, source_type: 'Copter'
  has_many :trucks, through: :moveable_locations, source: :moveable, source_type: 'Truck'
  has_many :ships, through: :moveable_locations, source: :moveable, source_type: 'Ship'
end

#app/models/train.rb

class Train < ActiveRecord::Base
  has_many :moveable_locations, as: :moveable, dependent: :destroy
  has_many :locations, through: :moveable_locations
end

#app/models/copter.rb

class Copter < ActiveRecord::Base
  has_many :moveable_locations, as: :moveable, dependent: :destroy
  has_many :locations, through: :moveable_locations
end

#app/models/truck.rb

class Truck < ActiveRecord::Base
  has_many :moveable_locations, as: :moveable, dependent: :destroy
  has_many :locations, through: :moveable_locations
end

#app/models/ship.rb

class Ship < ActiveRecord::Base
  has_many :moveable_locations, as: :moveable, dependent: :destroy
  has_many :locations, through: :moveable_locations
end

Using:

train1 = Train.create(title: 'Train1')
train2 = Train.create(title: 'Train2')
location1 = Location.create(title: 'Location1', train_ids: [train1.id, train2.id])
location2 = Location.create(title: 'Location2', trains: [train1, train2])
location3 = Location.create(title: 'Location3')
location3.train_ids << [train1., train2.id]
location4 = Location.create(title: 'Location34')
location4.trains << [train1, train2]
copter1 = Copter.create(title: 'Copter1', location_ids: [location1.id, location2.id]
copter2 = Copter.create(title: 'Copter1')
copter2.location_ids << [location1.id, location2.id, location3.id]
长安忆 2024-08-16 16:21:32

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

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

has many :through and polymorphic don't work together. If you try to access them directly, it should throw an error.
If i am not mistaken, you have to hand write widget.people and the push routine.

I don't think it is a bug, it is just something which hasn't been implemented yet. I would imagine we see it in the feature, because everyone has a case in which they could use it.

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