如何使用 rails 强参数允许散列

How to permit hash with rails strong params

我正在使用一个名为 element 的 atter_accessor 对象的模型。我想将表单数据数组传递给元素对象。在 Rails 控制台中,我收到 Unpermitted parameter 错误。

Parameters: {"authenticity_token"=>"[FILTERED]", "category"=>{"name"=>"asfd", "body"=>"asf", "element"=>{"1"=>"asfd:text", "2"=>"asfd:text", "3"=>"asfd:text"}}, "type"=>"text", "commit"=>"Create Category"}
Unpermitted parameter: :element. Context: { controller: CategoriesController, action: create, request: #<ActionDispatch::Request:0x0000000106b3ff68>, params: {"authenticity_token"=>"[FILTERED]", "category"=>{"name"=>"asfd", "body"=>"asf", "element"=>{"1"=>"asfd:text", "2"=>"asfd:text", "3"=>"asfd:text"}}, "type"=>"text", "commit"=>"Create Category", "controller"=>"categories", "action"=>"create"} }

模型中 attr_accessor :elements

在控制器中

def category_params
  params.require(:category).permit(:name, :body, :elements => []) 
end

我也尝试了很多替代方案,将 :elements 更改为 element: [],但没有任何效果。我想我在这里遗漏了一些东西,这就是我得到一个不允许的参数的原因。

您没有提到您正在使用的 rails 版本,但是, :elements => [] 不起作用,因为元素是 ruby 散列而不是数组

在rails 5.1+你可以使用

params.require(:category).permit(:name, :body, :elements => {}) 

除了 element / elements 命名问题之外还有很多混乱 - 选择一个并坚持下去。

如果您想在 Rack 应用程序中将数组作为 FormData 传递,您需要使用带空括号的键:

irb(main):001:0> str = "elements[]=a&elements[]=b&elements[]=c"                                                         => "elements[]=a&elements[]=b&elements[]=b"
irb(main):002:0> Rack::Utils.parse_nested_query(str)                                                                   
=> {"elements"=>["a", "b", "c"]}   

如果您将任何类型的值放在括号中,它将被解析为散列:

irb(main):003:0> str = "elements[1]=a&elements[2]=b&elements[3]=c"
=> "elements[1]=a&elements[2]=b&elements[3]=b"
irb(main):004:0> Rack::Utils.parse_nested_query(str)
=> {"elements"=>{"1"=>"a", "2"=>"b", "3"=>"c"}}    

当将空数组列入白名单时,将允许 permitted scalar values:

的数组
irb(main):005:0> params = ActionController::Parameters.new(Rack::Utils.parse_nested_query("elements[]=a&elements[]=b&elements[]=b"))
=> #<ActionController::Parameters {"elements"=>["a", "b", "b"]} permitted: false>
irb(main):006:0> params.permit(elements: [])
=> #<ActionController::Parameters {"elements"=>["a", "b", "b"]} permitted: true> 

当将哈希列入白名单时,您传递一个符号数组,代表您要允许的密钥:

irb(main):006:0> params = ActionController::Parameters.new(foo: { bar: 1, baz: 2, woo: 3 })
irb(main):007:0> params.permit(foo: [:bar, :baz])
=> #<ActionController::Parameters {"foo"=>#<ActionController::Parameters {"bar"=>1, "baz"=>2} permitted: true>} permitted: true>

您还可以通过传递空散列来允许具有任意键的散列:

irb(main):008:0> params.permit(foo: {})
=> #<ActionController::Parameters {"foo"=>#<ActionController::Parameters {"bar"=>1, "baz"=>2, "woo"=>3} permitted: true>} permitted: true>  

这是一个有点危险的操作,应该小心完成。