【问题标题】:"has_two" model relationship with polymorphic model?“has_two”模型与多态模型的关系?
【发布时间】:2014-11-18 16:06:11
【问题描述】:

我有一个像这样的多态 PLACE 模型:

class Place < ActiveRecord::Base
  belongs_to :placeable, polymorphic: :true
...

因此,例如,在我的 Lodging 模型中,我有类似的内容:

class Lodging < ActiveRecord::Base
has_one :place, as: :placeable, dependent: :destroy
...

它们按预期工作。 关键是现在我想创建一个 CarRental 模型,这个模型有两个地方,一个是接送地点,另一个是下车地点。

所以我写了:

class Transportation < ActiveRecord::Base
has_one :start_place, as: :placeable, dependent: :destroy
has_one :end_place, as: :placeable, dependent: :destroy

当然这行不通。关于如何做到这一点的任何见解?

编辑 1:如果我喜欢

class Transportation < ActiveRecord::Base
has_one :start_place, class_name: 'Place', as: :placeable, dependent: :destroy
has_one :end_place, class_name: 'Place', as: :placeable, dependent: :destroy

有效!但为什么?开始或结束信息保存在哪里?

** 编辑 2:不,它不起作用 ** 它不起作用... =(

【问题讨论】:

  • ...它有效,但您确定它正确有效吗?据我所见,它应该返回相同的开始和结束。因为,正如你所说,没有地方可以存储这些信息。
  • 你是对的。它不起作用@D-side。我的测试是错误的......

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


【解决方案1】:

我猜,之前的关联因为未知类而吐出错误。 has_one :start_place 默认情况下假定您的意思是一个不存在的类 StartPlace。它将术语单数化(尽可能地)并将其转换为CamelCase。一旦你指定你的意思是Place,就很清楚了。

无论如何,您应该添加一个新列。让我们尝试单表继承 (STI)。将string 类型的列type 添加到您的places 表中:

rails generate migration AddTypeToPlaces type:string

...确保它按照它说的做,然后像这样迁移并创建新模型:

rails generate model StartPlace --no-migration --parent=Place
rails generate model EndPlace   --no-migration --parent=Place

注意:它们没有得到专用表,并且继承自Place,而不是ActiveRecord::Base它应该生成两个空类,这很好,它们继承自Place 的东西。

...然后将您的关联恢复到不久前不起作用的内容:

has_one :start_place, as: :placeable, dependent: :destroy
has_one :end_place,   as: :placeable, dependent: :destroy

...它们现在应该可以工作了,因为 StartPlace 被定义为

Placetype 等于 "StartPlace"

...与EndPlace 相同,对应的type

我很久以前就描述过这个for a similar case

【讨论】:

  • 嘿@D-side,如果我的 Place 与 Start 和 End 位置相同,我该怎么办?
  • @Guido then this structure failed =) 你可以使用has_many :through,通过将相同的东西应用到连接模型(StartLink?)并像以前一样保留Place。这取决于您的应用逻辑,什么是最好的。
  • 或者你可以有两个对象并用一个方法比较它们是否在同一个地方。
  • 由于我将 Place 保持为多态,因为 Lodging、Activity 和其他事物可以有地点(位置),我想我也会将 has_one Place 添加到 Transportation 模型中。如果 Start 和 End 位置相同,我将保存这个位置。如果没有,我保存它们,但我不保存它并创建一个类进行比较。你怎么看?
  • @Guido 我不太了解您的应用程序的逻辑,无法提供建议。另一种解决方案是保留一个 Place 并使用多个 belongs_to 和相应的外键。
【解决方案2】:

您的架构对我来说没有意义 - 地方属于住宿等。当然有固定数量的地方,然后它们可以有许多不同的东西?在您的架构中,同一位置可能在数据库中出现很多次,这似乎是错误的。我也不认为多态关联是要走的路。

我会这样建模:

class Place
  has_many :lodgings
  has_many :starting_transportations, :class_name => "Transportation", :as => :start_place
  has_many :ending_transportations, :class_name => "Transportation", :as => :end_place

class Lodging
  belongs_to :place #using lodgings.place_id

class Transportation
  belongs_to :start_place, :class_name => "Place" #via transportations.start_place_id
  belongs_to :end_place, :class_name => "Place" #via transportations.end_place_id

顺便说一句,对于现实世界中的物理位置,我认为“位置”比“地点”更好。 “地点”听起来太模糊了。

【讨论】:

  • 感谢@max-williams 的回答。你是对的,Places 这个名字真的不是最好的选择,我正在考虑把它改成地点,正如你所说的。重点是我使用从 Google Places API 收集的信息填充 Place。所以,一个旅行有_many lodgings 和car_rentals,他们都有地方。因此,您认为最好的解决方案是检查该地点是否已存在,如果不存在则仅创建一个新地点?这里的重点是我允许用户编辑他们想要从 Place 获得的任何信息(例如街道、照片等)。
  • 你能看看我编辑的问题吗?我做了这些改变,它奏效了....
  • 一般来说,您的数据库中不应出现两次相同的位置。想想这个问题。 “鉴于我在 X 地,这里有什么住处?”
  • 感谢您的见解...我想这看起来很令人困惑,因为我一直在使用(并将更改)位置而不是位置。我的模型几乎是一个地址,lat lng 等。所以每个日志记录都有一个位置(地址)......
猜你喜欢
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
相关资源
最近更新 更多