如何获得强参数以允许嵌套的fields_for属性?

我有一个带有嵌套fields_for的表单。 我试图允许由该嵌套表单生成的参数,但它们被强参数阻止。 我使用rails 4.2.4和ruby 2.2.2

我读过一些官方文档:

  • http://api.rubyonrails.org/classes/ActionController/StrongParameters.html
  • http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters

我已经阅读了相关的SOpost:

  • Rails 4嵌套属性未允许的参数
  • 如何允许嵌套属性的强参数?

我读过各种博文:

  • http://www.rubyexperiments.com/using-strong-parameters-with-nested-forms/
  • http://adamyonk.com/2013/05/16/rails-4-strong-parameters-and-nested-forms.html
  • 和更多

我想我正在按照他们的意思去做,但我的嵌套属性被强参数拒绝了。 我在日志中得到了Unpermitted parameters: __template_row__, 0, 1, 2, 3

这是我的代码:

车型/ enclosure.rb

 class Enclosure  { order("year DESC, month DESC") }, dependent: :restrict_with_error validates :name, presence: true, uniqueness: {case_sensitive: false} accepts_nested_attributes_for :resident_animals, allow_destroy: true, reject_if: :all_blank def to_s name end end 

车型/ resident_animal.rb

 class ResidentAnimal < ActiveRecord::Base belongs_to :enclosure validates_presence_of :enclosure, :year, :month, :color ... end 

控制器/ enclosures_controller.rb

 class EnclosuresController < ApplicationController ... def update @enclosure = Enclosure.find(params[:id]) @enclosure.update(enclosure_params) respond_with @enclosure end private def enclosure_params params.require(:enclosure).permit(:name, :description, resident_animals_attributes: [:year, :month, :color, :id, :_destroy]) end end 

视图/隔音罩/ _form.html.erb

 

Resident Animals
Year * Month * Color * Remove

当我记录我的参数时,它们看起来像:

 {"enclosure"=>{"name"=>"Polar Quest", "description"=>"Polar bear attraction", "resident_animals_attributes"=>{"__template_row__"=>{"year"=>"2015", "month"=>"9", "color"=>"", "_destroy"=>"0"}, "0"=>{"year"=>"2005", "month"=>"8", "color"=>"white", "id"=>"1", "_destroy"=>"0"}, "1"=>{"year"=>"2012", "month"=>"7", "color"=>"yellow", "id"=>"2", "_destroy"=>"0"}, "2"=>{"year"=>"2011", "month"=>"3", "color"=>"white", "id"=>"4", "_destroy"=>"0"}, "3"=>{"year"=>"2006", "month"=>"2", "color"=>"yellowish", "id"=>"3", "_destroy"=>"0"}}}, "commit"=>"Update", "id"=>"1"} 

调用enclosure_params返回:

 {"name"=>"Polar Quest", "description"=>"Polar bear attraction", "resident_animals_attributes"=>{}} 

我究竟做错了什么?

谢谢!

我将在这里添加您的评论中的正确答案,这样这个问题就可以得到正确答案:

问题是.permit -ing包含ID作为键的嵌套哈希和其他属性的哈希作为值是一种特殊情况(很明显,因为它与.permit的典型参数结构不匹配)。

诀窍是:算法检测特殊情况(称为fields_for_style?因为它是通常由fields_for帮助程序提交的参数样式),并且仅当所有键都转换为整数时! 因此,如果密钥集中有非整数值(例如__template_row__new_record_id ),则它不会检测特殊情况,而是拒绝未明确允许的散列中的每个密钥(对于任何典型的哈希) )。

为了解决这个问题,给定原始post中的params结构,您可以简单地删除作为模板行的一部分提交的非整数键和属性:

 def enclosure_params params[:enclosure][:resident_animals_attributes].delete(:__template_row__) params.require(:enclosure).permit(...) # (no change from OP) end 

(当然这意味着,您应该确保您的界面不会尝试将有意义的数据作为模板行的一部分提交);)

 def enclosure_params params.require(:).permit(:name, :description, resident_animals_attributes: [:enclosure_id, :year, :month, :color] ) end 

我建议你使用更新的railsvalidation格式:

 validates: :enclosure_id, presence: true validates: :year, presence: true validates: :month, presence: true validates: :color, presence: true 

如果您确实需要在resident_animal上要求存在enclosure,则可能需要在依赖模型上使用inverse :. 我不确定你需要validation。

错误是指这一行

 <%= form.fields_for :resident_animals_attributes, ResidentAnimal.new(channel: form.object, year: Date.current.year, month: Date.current.month), index: "__template_row__" do |resident_animal_fields| %> 

特别是

 index: "__template_row__" do |resident_animal_fields| 

您没有定义索引属性。 尝试删除该键值对。