设计多态类

问题描述:

我们有一个使用2种模型的rails应用程序:图像和视频。 它们都属于收藏实体。 如果我们想要以统一的方式查询或使用这两种类型 - 我们不能。所以如果我们想取得最后15个,我们会查询两次,然后再排序,然后再取15个。 如果我们想找到()一些ID,我们需要总是得到它是什么类型 - 视频或图像...设计多态类

所以我们正在考虑如何解决这个问题。 持有指向任一个的资产模型? 它能够被急切加载吗?

在我看来,它必须是Asset.find(_id),并且我将无法识别图像或视频。

在Rails中解决这个问题的最简单或最正确的方法是什么?

谢谢!

+0

我认为在轨道'enum'是你正在寻找。 http://api.rubyonrails.org/v5.1/classes/ActiveRecord/Enum.html。希望这个帮助。 – thanhnha1103

+0

没有正确的方法来解决这个问题,因为它是[Object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch)的一个例子。解决这个问题的常用方法是使用单表或多表继承。 – max

+0

使用Tamer所描述的STI将允许您执行MediaItem.find(id)并根据结果获取视频或图像模型 – s1mpl3

您可以使用Single Table Inheritance来实现此目标。

比方说,你有一个模式叫Media

rails g model media_item type:string <other attributes here> 

然后你从中两款车型继承:VideoImage,像这样:

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关系为每个子类创建一个单独的属性 表,这种方式称为多表继承,但这也有其缺点。这完全取决于你的具体用例。

+2

“或者您可以为每个子类使用1对1关系创建单独的属性表“。这就是通常所说的多表继承。 – max

+0

@max非常感谢,我其实不知道它有一个名字哈哈。将相应地更新答案。 –

+0

我期待使用我现在的模型。你所建议的是我应该将我的整个模型和应用程序转换为MediaItem。 – Himberjack