我试图为Rails 5应用程序编写以下情况。 我有这两个型号:
class User < ApplicationRecord
has_many :mastered_games, class_name: 'Game', foreign_key: 'game_id'
has_and_belongs_to_many :played_games, class_name: 'Game', foreign_key: 'game_id'
end
class Game < ApplicationRecord
belongs_to :dungeon_master, class_name: 'User', foreign_key: 'user_id'
has_and_belongs_to_many :players, class_name: 'User', foreign_key: 'user_id'
end
这样的一般想法是任何用户都可以拥有许多玩过和掌握过的游戏,而且任何给定的游戏都只属于一个用户(一个DungeonMaster)并且有很多用户在玩游戏(玩家)。我知道使用模型名称可能会更容易,但这更具有词汇性,此外,关联可能会相互冲突。
我的迁移现在看起来像这样:
class CreateGames < ActiveRecord::Migration[5.1]
def change
create_table :games do |t|
t.integer :game_id
t.string :secret_key
t.belongs_to :dungeon_master, index: true
t.timestamps
end
end
end
class CreateUsers < ActiveRecord::Migration[5.1]
def change
create_table :users do |t|
t.integer :user_id
t.string :name
t.string :email
t.string :picture
t.string :provider
t.string :uid
t.timestamps
end
end
end
class CreateGamesUsersTable < ActiveRecord::Migration[5.1]
def change
create_join_table :games, :users do |t|
t.index :game_id
t.index :user_id
end
end
end
出于某种原因,这对我来说似乎不起作用。例如,当我尝试将一个dungeon_master添加到rails控制台中的游戏时,如下所示:
u = User.new(name: 'Jon')
g = Game.new()
g.dungeon_master = u
这将返回错误ActiveModel::MissingAttributeError: can't write unknown attribute user_id
。
此外,当我将一个用户添加到游戏中时,我遇到了多对多关联的双向性问题:
g.players << u
添加了用户但是当我尝试访问该用户的play_games时,它没有返回任何游戏。我可能遗漏了一些东西,但我无法弄清楚是什么。 任何帮助将不胜感激。
谢谢!
答案 0 :(得分:0)
你有一些方向性翻转。具有belongs_to
的任何模型都将在数据库表中接收外键。现在,您有一个games
表,其中包含game_id
列。你想要的是一个带有games
或user_id
列的dungeon_master_id
表(老实说,使用默认的外键名称而不是在模型中手动指定要容易得多):
create_table :games do |t|
t.references :dungeon_master
# other columns
end
create_table :users do |t|
# other columns
end
create_join_table(:games, :users)
然后你的模型有点简单:
class User < ApplicationRecord
has_many :mastered_games, class_name: 'Game', inverse_of: :dungeon_master
has_and_belongs_to_many :played_games, class_name: 'Game'
end
class Game < ApplicationRecord
belongs_to :dungeon_master, class_name: 'User', inverse_of: :mastered_games
has_and_belongs_to_many :players, class_name: 'User'
end
您不应该对以下内容有任何疑问:
user = User.new(name: 'Jon')
game = Game.new(dungeon_master: user)