简体   繁体   中英

Nested Attributes With JSON Rails One to Many

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:

  1. 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.

  2. "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).

  3. 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:

  1. 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 
  2. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM