简体   繁体   中英

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!

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.

I'm in the same boat: new to Rails and building a chess app. I started out using a has_and_belongs_to_many relationship between Players and Games, but I couldn't figure out how to properly model the white and black player roles this way.

I ended up using a different approach than what roboles suggested because I needed a way to follow the relationship from Player to Games.

First I added a third model called Seats, then setup my Player and Game models to have a has_many :through relationship like:

class Game < ActiveRecord::Base
  has_many :seats
  has_many :players, :through => :seats
end

class Player < ActiveRecord::Base
  has_many :seats
  has_many :games, :through => :seats
end

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

This sets up the model so that game.players and player.games work.

To track the white and black player, I added a column for color in the seats table:

create_table "seats", :force => true do |t|
  t.integer  "player_id"
  t.integer  "game_id"
  t.integer  "color"
  t.datetime "created_at", :null => false
end

Then in the game model I added some helper methods so that I can get the white player with game.white_player and set with game.white_player = foo

class Game < ActiveRecord::Base
...
def white_player
  Player.joins(:games).where(:seats => {:color => 0, :game_id => self.id}).first
end

def white_player=(player)
  self.players << player

  s = self.seats.find_by_player_id(player)
  s.color = 0
  s.save
end

I'm not sure if this is the best approach, but it seems to meet my requirements:

game.players # returns game's players
player.games # returns player's games
game.white_player # returns the white player
game.white_player = player # sets the white player

I'd be interested to know any ways to improve on this.

In your Game class add 2 fields like:

belongs_to :player_one, :class_name => "Player"
belongs_to :player_two, :class_name => "Player"

So this implies you have 2 integer fields in your DB player_one int, player_two int

The other models shouldnt have to change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM