Search code examples
ruby-on-railsruby-on-rails-3associationsmodel-associationsrails-models

RoR3 Model associations (Game belongs_to two Players)


I'm really new to Ruby on Rails 3 and I'm working on a simple chess game application. I plan to create the following models:

rails g model Player name:string
rails g model Game player_id_white:int player_id_black:int title:string
rails g model Comment player_id:int game_id:int comment_data:text
rails g model Move game_id:int player_id:int move_data:string

Assume they all have: id:int:primary_key, created_at:datetime, updated_at:datetime. I also omitted fields like 'password_hash' and others. My issue is with associations, not so much with what fields I need to make the app work.

class Player < ActiveRecord::Base
  has_many :games #some have player_id_black, others as player_id_white
  has_many :comments
  has_many :moves
end

class Game < ActiveRecord::Base
  has_many :comments
  has_many: moves
  **belongs_to :player1??**
  **belongs_to :player2??**
end

class Comment < ActiveRecord::Base
  belongs_to :player
  belongs_to :game
end

class Move < ActiveRecord::Base
  belongs_to :player
  belongs_to :game
end

Questions:

1) I want to link a Game to two Players, how can I specify that relationship?
2) Do I have to specify things like game_id:int in 'rails generate model' or is it implicit when I do the relationships (belongs_to :player, has_many :games)?

Thanks!


Solution

  • given the migration above you would want to set your Game model up as follows:

    class Game < ActiveRecord::Base
      has_many :comments
      has_many :moves
      belongs_to :white_player, :class_name => 'Player', :foreign_key => 'player_id_white'
      belongs_to :black_player, :class_name => 'Player', :foreign_key => 'player_id_black'
    end
    

    This will use your custom foreign keys, and enable you to link each association as a single belongs_to call!

    Alternatively, if you would like rails to 'guess' the foreign_key setting you would need to set up your migration like so:

    rails g model Game white_player_id:integer black_player_id:integer title:string
    

    If you do this, you would still need to specify the :class_name => 'Player' option for each of the belongs_to calls.