Мне потребовалось время, чтобы отследить эту ошибку, но я наконец выяснил почему . Я моделирую карточную игру, используя фреймворк Rails. В настоящее время моя база данных выглядит (в основном) так:
cards cards_games games
----- ----------- -----
id id id
c_type card_id ...
value game_id other_stuff
И Rails ActiveRecord card.rb и game.rb в настоящее время выглядят так
#card.rb
class Card < ActiveRecord::Base
has_and_belongs_to_many :player
has_and_belongs_to_many :game
has_and_belongs_to_many :cardsInPlay, :class_name => "Rule"
end
#game.rb
class Game < ActiveRecord::Base
has_and_belongs_to_many :cards
has_many :players
has_one :rules, :class_name => Rule
end
Когда я пытаюсь запустить игру с несколькими играми (более 1), я получаю сообщение об ошибке
ActiveRecord::StatementInvalid in GameController#start_game
# example
Mysql::Error: Duplicate entry '31' for key 1: INSERT INTO `cards_games` (`card_id`, `id`, `game_id`) VALUES (31, 31, 7)
Каждый раз, когда действие заканчивается неудачей, cardid == id. Это, я полагаю, связано с тем, как Rails вставляет данные в базу данных. Так как объекта cardsgames нет, я думаю, что он просто вставляет card_id в id и вставляет его в базу данных. Это прекрасно работает, пока у вас нет двух игр с одной картой, что нарушает ограничение первичного ключа для карточных игр. Будучи богатым с базами данных, мое первое решение этой проблемы состояло в том, чтобы попытаться заставить rails следовать «реальному» определению этих отношений, отбросив id и сделав cardid и gameid первичным ключом. Это не сработало, потому что миграция не могла справиться с наличием двух первичных ключей (несмотря на то, что Rails API говорил, что это нормально ... странно). Другое решение для этого состоит в том, чтобы опустить столбец 'id' в операторе INSERT INTO и позволить базе данных обрабатывать автоинкремент. К сожалению, я тоже не знаю, как это сделать.
Так, есть ли другой обходной путь для этого? Есть какой-то изящный трюк с Rails, которого я просто не знаю? Или такая структура не возможна в Rails? Это действительно расстраивает, потому что я знаю , что не так, и я знаю несколько способов исправить это, но из-за ограничений инфраструктуры Rail я просто не могу это сделать.