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

Rails嵌套属性创建Match与MatchPlayer时的参数及重复创建问题

Fixing the 3 MatchPlayer Records Issue in Your Rails App

Let's break down why you're ending up with 3 extra MatchPlayer entries, and get this sorted properly:

Why the Extra Records Are Happening

You're creating 3 MatchPlayer records for two key reasons:

  1. In your new action, you call @match.match_players.build, and since your Match model uses accepts_nested_attributes_for :match_players, Rails automatically creates a MatchPlayer for the opponent you select in the form when you save @match.
  2. On top of that, your original create action manually creates two more MatchPlayer records: one for current_player, and a duplicate one for the opponent.

Adding those up: 1 (auto-created from nested attributes) + 1 (current_player) + 1 (duplicate opponent) = 3 total records.

The Fix

We can simplify this to create only the two MatchPlayer records you need (current user + selected opponent) by leveraging Rails' nested attributes properly, without redundant manual creates.

1. Update the create Action

Remove the manual MatchPlayer.create calls, and instead build the current user's MatchPlayer before saving the match. This way, both records get saved in one go:

def create
  @match = Match.new(match_params)
  # Add the current player to the match's players before saving
  @match.match_players.build(player: current_player)
  
  if @match.save
    redirect_to(root_path, notice: "Success!")
  else
    render :new
  end
end

Note: I replaced save! with save because save! will raise an exception on validation failures, while save returns false and lets you render the form again with error messages.

2. Keep Your Updated Parameters & Form

Your current match_params and form code are already correct now that you're using the plural match_players (both in the form's simple_fields_for and the params permit):

  • Params: match_players_attributes: [:player_id] correctly matches the has_many :match_players association.
  • Form: f.simple_fields_for :match_players is the right plural syntax for a has_many nested form.

Optional: Clean Up the Form's Label Method

You can make the player label a bit cleaner with string interpolation:

= mp.input :player_id, collection: Player.all, label_method: ->(player) { "#{player.first_name} #{player.last_name}" }

With these changes, saving the match will create exactly two MatchPlayer records: one for the current user, and one for the opponent you select in the form—no duplicates, no extra entries.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 00:32:32