Reputation: 247
I have a HABTM relationship set up as follows:
class Game < ApplicationRecord
has_and_belongs_to_many :players
end
and
class Player < ApplicationRecord
validates :name, presence: true, uniqueness: true
has_and_belongs_to_many :games
end
When a new Game is being created, I want the user to be able to select existing Players to add to the game. In the Games#new view I have:
<%= 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.
In the controller I have
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
I know I should be appending player_ids but I'm not exactly sure how.
Upvotes: 0
Views: 201
Reputation: 101811
Use the collection helpers in your form:
<%= 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 %>
And then in your strong parameters you need to permit an array of scalar values:
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
Upvotes: 2