开发者

Rails 3: Should I use STI or just an extra column? (seeking advice)

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜