带有JSON Rails的嵌套属性,一对多

时间:2017-06-02 02:48:57

标签: mysql ruby-on-rails json nested-attributes ruby-on-rails-5.1

我正在用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。在许可证之后,控制器中的轨道是:

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

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

Rails返回:

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

gambiarra

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

如果我对嵌套属性执行此操作,那么在保存团队工作之前,团队1必须存在才能工作。如果我只保存团队,并且在创建关系之后,只有当我设置&#34; gambiarra&#34; 解决方案时,它才能运行。

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

1 个答案:

答案 0 :(得分:2)

您发送的参数结构不正确,rails希望使用嵌套属性

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

注意三件事:

  1. computer: null已被删除;您无需指定computer属性,因为其值将使用要创建的新计算机的id进行设置。

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

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

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

    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
      
    3. 只有在您使用表单助手创建嵌套表单时,@computer.speakers.build才是必需的。