如何构建这一点,以便从STI获得所有好处而不会产生什么后果? (我知道,这是不负责任的。)

假设我在Rails应用程序中有以下关联示例:

在此处输入图像描述

我正在考虑将STI下的* Posting模型结合起来。 STI的一个问题是许多属性的可能性仅与一个子类相关(即,许多非规范化的nil值)。 当你的子类和未来的发展和成长时,这尤其令人担忧。 我已经阅读了一些相关的post(例如这个 ),但是,正如您在我的示例中所看到的,潜在的子类特定字段不一定只是属性,而是很多belongs_to关联。

我的问题是,如何重构这个以使用来自Posting模型的STI来获取所有常见属性/方法(在我的实际应用程序中会有相当多的属性/方法),但保留特定的子类特定属性和belongs_to关联来自堆积在Posting模型中? 此外,访问@board.postings并使用这些标准方法的能力非常重要。

例如,我考虑过将特定于类型的属性移动到另一个模型:

 class CarPosting < Posting has_one: car_posting_detail end class CarPostingDetail < ActiveRecord::Base belongs_to :car_posting belongs_to :car_make belongs_to :car_model end 

虽然,这开始创建了很多连接,但我不确定我是否在正确的方向上有has_one / belongs_to声明,并且你必须开始链接调用(例如, @posting.car_posting_detail.car_make )。

您是否还有其他设计模式可以实现此目的?

您可以使用多态关联。

 Post model belongs_to :postable, :polymorphic => true 

汽车,事件和所有其他“可以”的课程将有这种关系

 has_many :posts, as: :postable 

Post会保留postable_id和postable_type

更多信息,请访问http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

你基本上有2个选项来完成inheritance。

首先,您可以按照建议使用rails STI。 缺点是最终使用不使用所有字段的子类的nil属性。 您希望通过向其他模型添加特定于类型的属性来减少此问题,这是减少此问题的好方法。 但是,您应该通过为Posting定义has_one :detail来尽可能将实现保持为DRY。 然后,您可以在发布子项中简单地指定特定的详细信息类型。 例如,CarPosting的详细信息将是CarPostingDetail。 这很方便,因为所有发布的孩子都会以相同的方式访问他们的详细信息,但仍会有不同的详细信息。 所以查询现在看起来像@posting.detail.car_make 。 为了更进一步,您可以在Posting模型中定义自定义帮助器方法,以获取当前Posting详细信息中的每个属性,并为其创建一个访问器。 现在整个细节层都是透明的,您可以通过说@posting.car_make来访问这些属性。

其次,您可以使用抽象类。 这基本上与STI相反。 您创建一个永远无法实例化的抽象模型类。 因此,您无法在Posting类中定义任何关系,因为它没有表。 抽象Posting类的每个子节点都有自己独立的表。 这样做的主要优点是能够为所有发布类型定义方法而无需复制并将其粘贴到每个模型中。 因此,如果模型之间存在一些重叠function,则此选项会更好,但数据重叠很少。