设计多态类
我们有一个使用2种模型的rails应用程序:图像和视频。 它们都属于收藏实体。 如果我们想要以统一的方式查询或使用这两种类型 - 我们不能。所以如果我们想取得最后15个,我们会查询两次,然后再排序,然后再取15个。 如果我们想找到()一些ID,我们需要总是得到它是什么类型 - 视频或图像...设计多态类
所以我们正在考虑如何解决这个问题。 持有指向任一个的资产模型? 它能够被急切加载吗?
在我看来,它必须是Asset.find(_id),并且我将无法识别图像或视频。
在Rails中解决这个问题的最简单或最正确的方法是什么?
谢谢!
您可以使用Single Table Inheritance来实现此目标。
比方说,你有一个模式叫Media
:
rails g model media_item type:string <other attributes here>
然后你从中两款车型继承:Video
和Image
,像这样:
rails g model video --parent=MediaItem
rails g model image --parent=MediaItem
现在在你的模型:
class MediaItem < ApplicationRecord
belongs_to :collection
end
class Collection < ApplicationRecord
has_many :media_items
end
此方法随附索姆尽管如此。例如,子类可能具有许多不同的属性,并且最终可能会有太多属性用于一个子类中,而不是另一个子类,反之亦然。
有一些解决方法,如有一个类似散列的properties
字段并包含子类特定的属性。但是,如果您需要对特定属性进行索引并且您的数据库不支持此类索引,则这可能也会出现问题。或者你可以用1对1关系为每个子类创建一个单独的属性 表,这种方式称为多表继承,但这也有其缺点。这完全取决于你的具体用例。
“或者您可以为每个子类使用1对1关系创建单独的属性表“。这就是通常所说的多表继承。 – max
@max非常感谢,我其实不知道它有一个名字哈哈。将相应地更新答案。 –
我期待使用我现在的模型。你所建议的是我应该将我的整个模型和应用程序转换为MediaItem。 – Himberjack
我认为在轨道'enum'是你正在寻找。 http://api.rubyonrails.org/v5.1/classes/ActiveRecord/Enum.html。希望这个帮助。 – thanhnha1103
没有正确的方法来解决这个问题,因为它是[Object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch)的一个例子。解决这个问题的常用方法是使用单表或多表继承。 – max
使用Tamer所描述的STI将允许您执行MediaItem.find(id)并根据结果获取视频或图像模型 – s1mpl3