You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails模型关联问题:Game模型关联两个User的实现困扰

Fixing Rails Game Model Association for Two Users

Hey there! Let's work through the issues in your Game model setup—you're close, but there are a few key mistakes throwing things off:

1. Wrong Association Type: has_one vs belongs_to

Your Game table stores user1_id and user2_id as foreign keys, which means each Game belongs to two User instances, not the other way around. Using has_one here is backwards: that would imply the User table has a game_id column pointing to a single Game, which isn't your use case. Switch these to belongs_to instead.

2. Typo-Ridden & Redundant Validations

Your validation rules have typos and unnecessary extra checks:

  • blank: false should be allow_blank: false (but you don't even need this)
  • nill: false is a typo—it's supposed to be allow_nil: false
  • The presence: true rule already covers both "not blank" and "not nil", so you can strip those extra flags entirely.

3. Dangerous dependent: :destroy Placement

Adding dependent: :destroy to these belongs_to associations would mean deleting a Game would delete the associated Users. That's almost certainly not what you want—you don't want to nuke a user's account just because one of their games gets removed. If you need to handle cleanup when a User is deleted, add the dependent rule on the User model side, or use dependent: :nullify here to set the game's user IDs to null if the user is deleted.

Corrected Game Model Code

class Game < ApplicationRecord
  has_secure_token

  # @!group RELATIONS
  has_many :turns, dependent: :destroy
  has_many :play_cards, dependent: :destroy
  belongs_to :user1, class_name: 'User'
  belongs_to :user2, class_name: 'User'
  # @!endgroup

  # @!group VALIDATORS
  validates :user1_id, presence: true
  validates :user2_id, presence: true
  # Optional: Add a check to prevent a user from playing against themselves
  validate :users_must_be_unique

  private

  def users_must_be_unique
    errors.add(:base, "A game can't have the same user for both players") if user1_id == user2_id
  end
  # @!endgroup
end

Bonus: Reverse Associations on User Model

If you want users to be able to access all games they're part of, add these to your User model:

class User < ApplicationRecord
  # Get games where this user is player 1
  has_many :games_as_player1, class_name: 'Game', foreign_key: 'user1_id', dependent: :nullify
  # Get games where this user is player 2
  has_many :games_as_player2, class_name: 'Game', foreign_key: 'user2_id', dependent: :nullify

  # Optional: Combine both into a single handy association
  def games
    Game.where("user1_id = ? OR user2_id = ?", id, id)
  end
end

Quick Migration Check

Make sure your games table has the required foreign key columns. If not, run this migration:

rails generate migration AddPlayerReferencesToGames user1:references user2:references
rails db:migrate

内容的提问来源于stack exchange,提问作者Alexis CHEVREUX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:59:34