JSON Rails 一对多的嵌套属性

Nested Attributes With JSON Rails One to Many

我在想 nested_attribute 的问题。

team.rb:

class Team < ApplicationRecord
  has_many :players, dependent: :destroy
  accepts_nested_attributes_for :players, allow_destroy: true
end

控制台输出:

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

因此,我忽略控制器中的 team_id 以创建并将其作为 null 发送给 player_id。获得许可后 rails 进入控制器的是:

team: {name:'testes team', players_attributes: [{ name: 'testes'}]}

在我看来(可能是我的错误)rails 应该以这种方式提供这种关系。我测试了它删除嵌套属性 idteam_id 但不起作用。

Rails return:

bodyText: "{"players.team":["must exist"]}

控制器:

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

甘比亚拉:

@team.players.each do |player|
  player.team_id = 1
end

如果我在保存团队之前对嵌套属性执行此操作,则团队 1 必须存在才能工作。如果我只保存团队并在创建关系后它也不起作用,只有当我设置 "gambiarra" 解决方案时。

如何解决这个关系?如前所述,我的控制器仅过滤嵌套数据的属性。如果我使用 HTML 提交,工作正常,如果我使用 JSON 作为嵌套对象,它不起作用,除非我强制关系找到 a team_id我的播放器在保存 等之前,rails 将保存并提交正确的播放器,正如我的播放器中没有 team_id 时预期的那样。

您发送的参数结构不正确,rails 需要这样的东西才能使用 嵌套属性:

{
  "computer": {
    "speakers_attributes": {
      "0": {
        "power": "1"
      }
    }
  }
}

注意三件事:

  1. computer: null 已删除;您不需要指定 computer 属性,因为它的值将由要创建的新计算机的 id 设置。

  2. 添加了
  3. "0":;由于 has_many :speakers 关联,您可以创建多个 Speaker(您将使用 1: { ... }, 2: { ... },依此类推)。

  4. speaker:改为speakers_attributes;这就是 rails 识别 嵌套属性 值的方式。

现在参数已经设置正确,你还需要做两件事:

  1. 确认您的关联设置正确

    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. 正确设置您的控制器

    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
    

此处 @computer.speakers.build 仅当您要使用表单助手创建嵌套表单时才需要。