I'm figuring a problem with a nested_attribute.
team.rb:
class Team < ApplicationRecord
has_many :players, dependent: :destroy
accepts_nested_attributes_for :players, allow_destroy: true
end
console output:
Processing by TeamsController#create as JSON
Parameters: {"team"=>{"id"=>nil, "name"=>"testes",
"players_attributes"=>[{"id"=>nil, "name"=>"dadada", "_destroy"=>false, "team_id"=>nil}]}}
Unpermitted parameter: id
So, i'm ignoring team_id
in controller for create and sending it as null same to player_id
. What rails is getting in controller after permit is:
team: {name:'testes team', players_attributes: [{ name: 'testes'}]}
In my opinion (prob my mistake) rails should feed this relation in exactly this way. I tested it removing the nested attribute id
and team_id
but doesn't works.
Rails return:
bodyText: "{"players.team":["must exist"]}
controller:
def create
@team = Team.create(team_params)
@team.players.each do |player|
player.team_id = 1
end
respond_to do |format|
if @team.save
format.html { redirect_to @team, notice: 'Team was successfully created.' }
format.json { render :show, status: :created, location: @team }
else
format.html { render :new }
format.json { render json: @team.errors, status: :unprocessable_entity }
end
end
end
def team_params
params.require(:team).permit(:name, players_attributes: [:name, :positions, :_destroy])
end
gambiarra:
@team.players.each do |player|
player.team_id = 1
end
If i do this to the nested attribute BEFORE save team it works, team 1 must exists for it to work. If i save only the team and after create the relation it DOESN'T works either, only if I set the "gambiarra" solution.
How to solve this relation? As mentioned, my controller is filtering for only attributes for nested data. If i submit with HTML, works fine, if i use a JSON as nested objects, it doesn't work unless i force the relation to find a team_id
for my player before save and so on, rails will save and commit the right player as is expected to do without a team_id
in my player.
The structure of the params you are sending is incorrect, rails expects something like this in order to work with nested attributes:
{
"computer": {
"speakers_attributes": {
"0": {
"power": "1"
}
}
}
}
Notice three things:
computer: null
was removed; you don't need to specify computer
attribute since its value will be set with the id
of the new computer to be created.
"0":
was added; because of the has_many :speakers
associations, you can create more than one Speaker
(you will use 1: { ... }, 2: { ... }
, and so on).
speaker:
was changed to speakers_attributes
; that's the way rails recognizes nested attributes values.
Now that the parameters had been set correctly, you need to do two more things:
Confirm that your associations are set correctly
class Computer < ApplicationRecord
has_many :speakers, dependent: :destroy
accepts_nested_attributes_for :speakers, allow_destroy: true
end
class Speaker < ApplicationRecord
belongs_to :computer
end
Properly setup your controller
class ComputersController < ApplicationController
def new
@computer = Computer.new
@computer.speakers.build
end
def create
@computer = Computer.create(computer_params)
if @computer.save
# handle success
else
# handle error
end
end
# other actions
private
def computer_params
params.require(:computer).permit(speakers_attributes: [:power])
end
end
Here @computer.speakers.build
is neessary only if you will be creating nested forms using form helpers.