Вы не открываете здесь никаких новых возможностей, и у Rails есть стандартные способы сделать все это.Но легко «сойти с рельсов» и сделать его сложнее, чем нужно.
Концептуально, перестаньте думать об обновлении связки Players
и начните думать об обновлении Game
, которое происходитиметь немного Players
. документы удивительно полезны здесь.
Давайте сначала перейдем к вашей модели игры.Вам нужно будет сказать, что все в порядке, чтобы обновить вложенные атрибуты для игроков, как это:
# models/game.rb
model Game < ApplicationRecord
has_many :players
accepts_nested_attributes_for :players
end
Ваше представление генерирует параметры, которые не совсем стандартны.Опять же, пусть Rails сделает всю работу за вас.Вам не нужны скрытые поля или each_with_index.Поскольку мы находимся в Rails 5, давайте использовать новый помощник form_with
, и мы позволим fields_for
выполнять свою работу, не пытаясь объяснить, как индексировать:
# views/games/edit_players.html.erb
<h2> Edit Players </h2>
<%= form_with(model: game, local: true) do |form| %>
<div>
Game name: <%= form.text_field :name %>
</div>
<%= form.fields_for :players do |player_fields| %>
<div>
Player name: <%= player_fields.text_field :name %><br>
</div>
<% end %>
<div>
<%= form.submit %>
</div>
<% end %>
Это сгенерируетпараметры, которые выглядят примерно так:
Parameters: {"game"=>
{"name"=>"Risk",
"players_attributes"=>
{"0"=>{"name"=>"Abel", "id"=>"1"},
"1"=>{"name"=>"Baker", "id"=>"2"},
"2"=>{"name"=>"Charlie", "id"=>"3"}}},
"commit"=>"Update Game",
"id"=>"1"}
Теперь вам даже не нужно настраивать конечную точку обновления.Просто используйте ваше стандартное действие GamesController#update
:
# controllers/games_controller.rb
class GamesController < ApplicationController
...
def edit_players
@game = Game.find(params[:id])
end
def update
@game = Game.find(params[:id])
if @game.update(game_params)
redirect_to @game
else
render :edit
end
end
private
def game_params
params.require(:game).permit(:name, players_attributes: [:id, :name])
end
end
Наконец, ваш файл маршрутов сбивает с толку, потому что вы используете collection
(который не ожидает: id) вместо member
.Файл маршрутов должен выглядеть примерно так:
# routes.rb
Rails.application.routes.draw do
resources :players
resources :games do
member { get :edit_players }
end
end