I am working on a project (Rails 3.0.3) where I think I may need to use STI, but I am not sure if I should just add an extra column to a table and be done with it.
In my object model, (for a gaming system) I have players (who belong to agencies) and owners (who own the agencies).
Both players and owners are owned by agents, which is a user account, so an agent can be a player and/or owner in many agencies.
I should have named agent 'user' instead, oops. So I have this:
class Agency 开发者_JAVA百科< 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 and Owner both share exactly the same attributes, the only difference between the two is that Owner has a different relationship with Agency than Player does (the Owner owns the Agency, the Agency only has one Owner, but has many players).
Additionally, the Owner is given special rights, such as the ability to adjust the settings in an agency.
From a pure OOP perspective, Owner is a subclass of Player (or, Owner and Player are both subclasses of some undefined class like Participant or something), but when accounting for persistence, it seems like poor database design to have separate players and owners tables.
My first thought was to refactor and employ STI and either make Owner a subclass of Player or introduce a new base class and then subclass both Owner and Player.
My other thought was that I could just add a boolean/tinyint column to Player called is_owner, but I can forsee that potentially leading to some nasty view and controller code.
I was wondering if anyone out there has run into a similar circumstance and maybe has any advice or could point me to some good online resources to read up on STI?
Maybe you should think of Player
and Owner
as relations between Agent
and Agency
. So an Agent
owns an Agency
and an Agent
plays games of an Agency
. Hence you might introduce the concept of a role and hence a model Role
from which Player
and Owner
inherit. The question is: Do you ever want to use the Role
model? Or is your application about owners and players and except of some common attributes they are two totally different kind of things?
If they are two different things, then you should make them two different models. If you have some code duplication between the two models, then you might use a (or multiple) mixin(s) to share code between them.
In general I prefer composition over inheritance. In the first place inheritance looks like an elegant way to share code between classes but it isn't about that. Inheritance is about types and interfaces. Hence you couple things in terms of their interfaces. This is strong constraint in the further development of your models.
I use inheritance only if there is real is_a
relation and not a shares_some_code_with
relation between to classes. And more important: I use it if and only if it has an technical advantage for me. Otherwise there are much better ways to share code between classes in ruby.
精彩评论