多态STI设置

时间:2011-03-05 05:07:08

标签: ruby-on-rails ruby-on-rails-3 activerecord

我有一个广泛使用实体模型的应用程序。

在这个应用程序的过去版本(处理重写,当前版本是PHP)中,这是使用单个表继承建模的,基本上有两个相同的模型。

  • 一个模型是Entity,它与项目相关联,有多种类型(客户端,请求者,提供者等)。

  • 另一个模型是Addressbook,它与实体大致相同,除了不同的表和型号名称以及一些仅限地址簿的字段(例如禁用)。

我们目前在addressbook_id的实体上有一列用于将项目实体映射回地址簿,或者我们尝试根据电子邮件地址进行映射失败。地址簿和实体之间的数据不保持同步,也就是说,必须能够更新项目中的实体而不会对地址簿中的数据产生任何影响(尽管我们提供了更新地址簿的选项)。 / p>

无论如何,有4种或5种实体。它们大多数都是相同的字段(名字,姓氏,电子邮件,地址,电话等)。每个实体类型可能有1-3个字段,这些字段对于它是唯一的,但就此而言。除了当前app中的实体,实体可能是人或公司(相同的STI表,也有company_name字段)。

对于应用程序需要做什么,轻松找到项目的所有实体(无论类型或是否是人或公司)都是一种胜利。还能够轻松地在查询中加入实体,并按项目搜索它们,获胜。

因此,我倾向于坚持STI模式并保持简单,并且由于每种类型共享90%的相同字段,因此不会浪费很多。但是,我很好奇是否有任何好的建议来处理为Addressbook和Entity提供基本相同的模型的整个问题,但是将数据保存在单独的表中。我已经考虑过多态关联可能有什么帮助,但我认为这会使表结构更复杂,并且可能会损害查询的性能(相当大的数据集,这些实体可能包含在列表视图中)。

但我真的不想最终结果......

class Entity

class Customer < Entity

class Addressbook

class AddressbookCustomer < Addressbook

etc...

非常糟糕,实体类型和子类型之间存在共同的功能(例如,Entity和Addressbook都有一个返回全名的名称方法,而Customer和AddressbookCustomer都可能有一个last_order方法)。 / p>

当前数据只存储在两个表中,地址簿和实体都有一个类型列。然而,这是一个干净的休息,所以不必保留遗留的表结构,但是从保持简单的角度来看,我喜欢这种结构。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

我从来没有这样做,但是如果你想在所有“实体”之间共享代码,为什么不创建一个其他所有继承的基类:

class OneClassToRuleThemAll < ActiveRecord::Base
  def name
  ...


class Entity < OneClassToRuleThemAll
  set_table_name "entities"

class AddressBook < OneClassToRuleThemAll
  set_table_name "address_books"

它为您提供了一个共享方法的基类,但为继承树中的每个分支提供了单独的表。

如果您不喜欢该解决方案,因为您仍然想要共享不属于OneClassToRuleThemAll但在树下更远的表兄弟类之间共享的方法,那么为什么不写一个小模块来保持那些函数,比如last order,然后将该模块导入到需要这些函数的每个表兄弟类中?

P.S。我甚至不知道第一个例子是否有效,但我认为应该这样。