向 has_and_belongs_to_many 关系添加多条记录

Posted

技术标签:

【中文标题】向 has_and_belongs_to_many 关系添加多条记录【英文标题】:Add multiple records to has_and_belongs_to_many relationship 【发布时间】:2021-08-14 00:39:39 【问题描述】:

我的 HABTM 关系设置如下:

class Game < ApplicationRecord
  has_and_belongs_to_many :players
end

class Player < ApplicationRecord
  validates :name, presence: true, uniqueness: true
  has_and_belongs_to_many :games
end

创建新游戏时,我希望用户能够选择现有玩家添加到游戏中。在 Games#new 视图中,我有:

<%= form_with(model: game) do |f| %>
  <h3>Select players participating in this game</h3>

  <% @players.each do |player| %>
    <div class="field">
      <%= check_box_tag :player_ids, player.id, false,  id: "player_#player.id" %>
      <%= label_tag "player_#player.id", player.name %>
    </div>
  <% end %>


  <div class="actions">
    <%= f.submit 'Start Game' %>
  </div>
<% end %>

This displays each user with a checkbox to select, but when multiple players are selected and a game is created, only the last player is associated with the game.

在我的控制器中

  def new
    @game = Game.new
    @players = Player.all.sort_by &:name
  end

  def create
    @game = Game.new(game_params)

    respond_to do |format|
      if @game.save
        format.html  redirect_to @game 
        format.json  render :show, status: :created, location: @game 
      else
        format.html  render :new, status: :unprocessable_entity 
        format.json  render json: @game.errors, status: :unprocessable_entity 
      end
    end
  end

  private

  def set_game
    @game = Game.find(params[:id])
  end

  def game_params
    params.permit(:player_ids)
  end

我知道我应该附加 player_ids,但我不确定如何。

【问题讨论】:

【参考方案1】:

在表单中使用集合助手:

<%= form_with(model: game) do |f| %>
  <h3>Select players participating in this game</h3>

  <div class="field">
    <%= f.collection_check_boxes(:player_ids, @players, :id, :name) %>
  </div>

  <div class="actions">
    <%= f.submit 'Start Game' %>
  </div>
<% end %>

然后在你的强参数中你需要允许一个标量值数组:

class PlayersController
  def new
    @game = Game.new
    # Sort the records in the DB, not in Ruby land.
    @players = Player.all.order(:name)
  end

  def create
    @game = Game.new(game_params)
    respond_to do |format|
      if @game.save
        format.html  redirect_to @game 
        format.json  render :show, status: :created, location: @game 
      else
        format.html do
           # required to render the form
           @players = Player.all.order(:name) 
           render :new, status: :unprocessable_entity 
        end
        format.json  render json: @game.errors, status: :unprocessable_entity 
      end
    end
  end

  private

  def set_game
    @game = Game.find(params[:id])
  end

  def game_params
    params.require(:game)
          .permit(player_ids: [])
  end
end

【讨论】:

谢谢!这成功了,在视图文件中也更干净了?。我确实必须在强参数中要求游戏,否则它们会被过滤掉。 params.require(:game).permit(player_ids: [])

以上是关于向 has_and_belongs_to_many 关系添加多条记录的主要内容,如果未能解决你的问题,请参考以下文章

has_and_belongs_to_many 连接表的 Rails 迁移

collection_select 和 has_and_belongs_to_many 关系

rails:关联表(has_and_belongs_to_many)不保存任何记录

将记录添加到 has_and_belongs_to_many 关系

在“has_many :through”和“has_and_belongs_to_many”之间进行选择

如何为 has_and_belongs_to_many 关系设置我的装置?