3

我正在做一个项目(Rails 3.0.3),我认为我可能需要使用 STI,但我不确定是否应该在表中添加一个额外的列并完成它。

在我的对象模型中,(对于游戏系统)我有玩家(属于代理商)和所有者(拥有代理商)。

玩家和所有者都归代理所有,代理是一个用户帐户,因此代理可以是许多代理中的玩家和/或所有者。

我应该将代理命名为“用户”,哎呀。所以我有这个:

class Agency < ActiveRecord::Base
  has_many :players, :class_name => "Player", :foreign_key => "agency_id"
  has_many :agents, :through => :players, :source => :agent_id
  has_one :owner, :class_name => "Owner", :foreign_key => "agency_id"
end

class Player < ActiveRecord::Base
  belongs_to :agency, :class_name => "Agency", :foreign_key => "agency_id"
  belongs_to :agent, :class_name => "Agent", :foreign_key => "agent_id"
end

class Owner < ActiveRecord::Base
  belongs_to :agency, :class_name => "Agency", :foreign_key => "agency_id"
  belongs_to :agent, :class_name => "Agent", :foreign_key => "agent_id"
end

Player和Owner的属性完全相同,唯一不同的是Owner与Agency的关系与Player不同(Owner拥有Agency,Agency只有一个Owner,但有很多玩家)。

此外,所有者被赋予特殊权利,例如调整代理机构中的设置的能力。

从纯粹的 OOP 角度来看,Owner 是 Player 的子类(或者,Owner 和 Player 都是某些未定义类的子类,例如 Participant 或其他东西),但是考虑到持久性,拥有单独的 player 和 owner 表似乎是糟糕的数据库设计.

我的第一个想法是重构和使用 STI,或者让 Owner 成为 Player 的子类,或者引入一个新的基类,然后将 Owner 和 Player 子类化。

我的另一个想法是我可以向 Player 添加一个名为 is_owner 的 boolean/tinyint 列,但我可以预见这可能会导致一些讨厌的视图和控制器代码。

我想知道那里是否有人遇到过类似的情况,也许有任何建议或可以向我指出一些好的在线资源来阅读 STI?

4

1 回答 1

1

也许您应该将Playerand视为andOwner之间的关系。所以 an拥有an并且 anan的游戏。因此,您可能会引入角色的概念,从而引入模型并从中继承。问题是:您是否曾经想使用该模型?或者你的应用程序是关于所有者和玩家的,除了一些共同的属性之外,它们是两种完全不同的东西?AgentAgencyAgent AgencyAgent AgencyRolePlayerOwnerRole

如果它们是两个不同的东西,那么你应该把它们做成两个不同的模型。如果您在两个模型之间有一些代码重复,那么您可以使用一个(或多个)mixin 在它们之间共享代码。

一般来说,我更喜欢组合而不是继承。首先,继承看起来像是在类之间共享代码的一种优雅方式,但它不是这样的。继承是关于类型和接口的。因此,您可以根据它们的接口来耦合事物。这对您的模型的进一步发展是一个强有力的限制。

仅当存在真正的is_a关系而不是shares_some_code_with与类之间的关系时,我才使用继承。更重要的是:当且仅当它对我有技术优势时,我才会使用它。否则,有更好的方法可以在 ruby​​ 中的类之间共享代码。

于 2012-02-24T11:47:42.007 回答