views:

36

answers:

1

I have an application which has the following characteristics

There are Clubs
Each Club has Teams
Each Team has Players

I have a users table. The user table basically contains the username and password for the club manager, team manager and the player to login to the system.

How should I structure the models and the tables?

I plan to create tables for Club, Team and Players. But I am not sure show to structure the relationship between them and the users table.

I could create user_id in each of the model, but the relationship would be Club belongs_to User which doesn't seems right. Moreover I would end up with a User model that has the following

has_one :club
has_one :team
has_one :player

Which is not right. A user will have only one of them at any given time.

Is there a better way to structure this?

A: 

Under Rails, has_one is really "has at most one". It's perfectly valid to have all three has_one decorators in User. If you want to ensure they only have precisely one, you could add a validation, for instance:

class User < ActiveRecord::Base
  has_one :club
  has_one :team
  has_one :player

  validate :has_only_one

  private

  def has_only_one
    if [club, team, player].compact.length != 1
      errors.add_to_base("Must have precisely one of club, team or player")
    end
  end
end

Since you have the ability to change the users table in the database, I think I would put club_id, team_id, player_id in users, and have the following:

class Club < ActiveRecord::Base
  has_one :user
  has_many :teams
  has_many :players, :through => :teams
end

class Team < ActiveRecord::Base
  has_one :user
  belongs_to :club
  has_many :players
end

class Player < ActiveRecord::Base
  has_one :user
  belongs_to :team
  has_one :club, :through => :team
end

class User < ActiveRecord::Base
  belongs_to :club
  belongs_to :team
  belongs_to :player

  validate :belongs_to_only_one

  def belongs_to_only_one
    if [club, team, player].compact.length != 1
      errors.add_to_base("Must belong to precisely one of club, team or player")
    end
  end
end

I'd even be tempted to rename User as Manager, or have has_one :manager, :class_name => "User" in the Club, Team and Player models, but your call.

Chris
I thought about adding the three ids in the user table. How would we go about identifying the "entity" who has logged in. For each user there will be only one of the club_id or team_id or player_id. I will have check all three to see if the user belongs to a club, team or player. Any better way to go from the `User` model to Club/Team/Player?
so1o
I suspect you could do something clever with `abstract_class?` or polymorphic association; but I'd be inclined just to have a method in User like `def managed ; club || team || player ; end`
Chris