0

我正在解决nested_attribute 的问题。

团队.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但不起作用。

导轨返回:

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 作为嵌套对象,它不起作用,除非我强制关系在保存之前为我的播放器找到一个team_id,等等,rails 将保存并提交正确的播放器是预计team_id在我的播放器中没有一个。

4

1 回答 1

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 识别嵌套属性值的方式。

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

  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将使用表单助手创建嵌套表单时,才需要这样做。

于 2017-06-02T04:22:23.907 回答