RoR3 Модельные ассоциации (игра принадлежит двум игрокам) - PullRequest
1 голос
/ 06 октября 2011

Я действительно новый в Ruby on Rails 3, и я работаю над простым приложением для игры в шахматы.Я планирую создать следующие модели:

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

Предположим, что у них всех есть: id: int: primary_key, creation_at: datetime, updated_at: datetime.Я также пропустил такие поля, как 'password_hash' и другие.Моя проблема связана с ассоциациями, а не с тем, какие поля мне нужны, чтобы приложение работало.

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

Вопросы:

1) Я хочу связать игру с двумя игроками, как я могу указать эти отношения?
2) Нужно ли указывать такие вещи, как game_id:int в 'rails Generate Model' или это неявно, когда я делаю отношения (принадлежат: игрок, has_many: игры)?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 06 октября 2011

, учитывая вышеописанную миграцию, вы захотите настроить модель игры следующим образом:

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

При этом будут использоваться ваши собственные внешние ключи, и вы сможете связывать каждую ассоциацию как единый вызов принадлежащий_

В качестве альтернативы, если вы хотите, чтобы rails 'угадал' настройку foreign_key, вам нужно настроить миграцию следующим образом:

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

Если вы сделаете это, вам все равно нужно будет указать опцию: class_name => 'Player' для каждого из вызовов assign_to.

2 голосов
/ 28 января 2013

Я в одной лодке: новичок в Rails и создание шахматного приложения.Я начал использовать отношения has_and_belongs_to_many между игроками и играми, но я не мог понять, как правильно смоделировать роли белых и черных игроков таким образом.Мне нужен был способ проследить отношения между игроком и играми.

Сначала я добавил третью модель под названием «Места», а затем настроил свои модели игрока и игры, чтобы иметь отношение has_many: through, например:

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

Это настраивает модель так, чтобы работали game.players и player.games.

Чтобы отследить белого и черного игрока, я добавил колонку для цвета в таблице мест:

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

Затем в игровой модели я добавил несколько вспомогательных методов, чтобы я мог получить белого игрока с помощью game.white_player и установить с помощью 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

Я не уверен, что этонаилучший подход, но, похоже, он отвечает моим требованиям:

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

Мне было бы интересно узнать, как можно улучшить это.

0 голосов
/ 06 октября 2011

В вашем классе Game добавьте 2 поля, например:

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

Таким образом, это означает, что у вас есть 2 целочисленных поля в вашей БД player_one int, player_two int

Другие модели не должны меняться.

...