我正在做一个项目(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
玩家和所有者都具有完全相同的属性,两者之间的唯一区别是所有者与代理商的关系与玩家的关系不同(所有者拥有代理机构,代理机构只有一个所有者,但拥有许多玩家(。
此外,所有者还被授予特殊权限,例如在代理机构中调整设置的能力。
从纯粹的 OOP 的角度来看,所有者是 Player 的子类(或者,所有者和玩家都是某个未定义的类的子类,如参与者或其他东西(,但是在考虑持久性时,拥有单独的玩家和所有者表似乎是糟糕的数据库设计。
我的第一个想法是重构和使用 STI,要么使所有者成为播放器的子类,要么引入一个新的基类,然后同时子类所有者和播放器。
我的另一个想法是,我可以向名为 is_owner 的 Player 添加一个布尔/微小列,但我可以预见这可能会导致一些讨厌的视图和控制器代码。
我想知道是否有人遇到过类似的情况,也许有任何建议,或者可以指出我一些好的在线资源来阅读 STI?
也许你应该把Player
和Owner
看作是Agent
和Agency
之间的关系。所以一个Agent
拥有一只Agency
,一个Agent
玩一个Agency
的游戏。因此,您可以引入角色的概念,从而引入Player
和Owner
继承的模型Role
。问题是:您是否想使用Role
模型?或者你的应用程序是关于所有者和玩家的,除了一些共同的属性之外,它们是两种完全不同的东西?
如果它们是两个不同的东西,那么你应该让它们成为两个不同的模型。如果两个模型之间存在一些代码重复,则可以使用一个(或多个(mixin(或多个(在它们之间共享代码。
总的来说,我更喜欢作曲而不是继承。首先,继承看起来像是在类之间共享代码的一种优雅方式,但事实并非如此。继承与类型和接口有关。因此,您在接口方面进行了耦合。这是模型进一步开发中的强约束。
只有当类之间存在真正的is_a
关系而不是shares_some_code_with
关系时,我才使用继承。更重要的是:当且仅当它对我有技术优势时,我才会使用它。否则,在 ruby 中的类之间共享代码有更好的方法。