使用STI和类别的优点是什么?

时间:2011-11-03 03:56:05

标签: ruby-on-rails single-table-inheritance

这来自Rails世界,但是关于单表继承的一个非常通用的问题。他们只是因为我问这是因为当没有明显的理由时,人们继续向我推销STI。可能是我错过了一些观点?请考虑这两种情况以便显示&存储网站上各种页面的页面内容:

场景1

class ContentItem < ActiveRecord::Base
  belongs_to category
end

此处所有可能的项目都存储在一个表格中,仅按类别进行区分。然后,只要您需要显示所有新闻项目或常见问题项目,您只需拨打类别。

场景2

class ContentItem < ActiveRecord::Base

end

class FaqItem < ContentItem
end

class NewsItem < ContentItem
end

此处不需要类别,但如果您需要添加其他类型的ContentItem,则需要创建另一个模型,而另一个模型等等。

我对场景#2的问题是FaqItem&amp; NewsItems完全一样。他们永远不会有所不同。唯一的区别是他们可以被不同的人修改(网站管理员与公关人员的新闻)。

因此,虽然两种方法都可以,但为什么在这个特定实例中选择一种方案呢?

3 个答案:

答案 0 :(得分:2)

如果只有少数类别或类型,并且共享了大量代码,则将其放在一个类中是非常易于管理的。但是一旦列表增长,您的代码将分散在case语句或if - 树中,这就是继承派上用场的地方。

例如:

def title
  case category_id
    when 'FaqItem'
      do_1_thing
    when 'NewsItem'
      do_another_thing
  end
end

而不是

class FaqItem < ContentItem
  def title
    do_1_thing
  end
end  

class NewsItem < ContentItem
  def title
    do_another_thing
  end
end  

第二种解决方案将更易于维护和理解。可能存在一些重复的代码,但这可以通过巧妙地使用您的父类来解决。

仍然:转换为使用STI的时间很快,这取决于代码的复杂程度。

答案 1 :(得分:1)

我不熟悉术语“单表继承”,但它看起来像是关于子类化与类型代码的标准参数的实例。人们争论这个因为两种选择都是正确的选择,具体取决于具体情况。我务实的建议是:根据更大的背景,选择任何一种策略可以减少代码重复。不仅要考虑现在的类别,还要考虑将来需要添加新类别的可能性。

答案 2 :(得分:1)

我喜欢在Rails中使用STI(a)你需要在一个或多个子类中有一些特定的行为,(b)你将在应用程序的不同部分进行父类和子类查找。

在您给出的示例中,可能所有ContentItem都具有“title”属性。但也许FaqItem也需要一个“回答”属性,也许这个属性是通过验证所必需的。

此外,也许您的应用需要一个仅包含常见问题解答(FaqItem.all)的常见问题解答页面。但也许它还需要一个包含所有内容项(或搜索功能)的完整索引页。

这样的东西是STI派上用场的地方。

(也不要忘记在类型列上创建索引)