5

I am working on a Model with an atter_accessor object named element. I want to pass the Array of form data to the element object. In Rails console I am getting Unpermitted parameter error.

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"} }

In model attr_accessor :elements

In controller

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

I tried with many alternatives changing the :elements to element: [] too, nothing worked. I think I am missing something here which is the reason I am getting an unpermitted parameters.

5
  • I’m not sure with this, but you can try params.permit(:name, :body, element: []) Commented Feb 19, 2022 at 4:50
  • I tried, didn't worked. Am I going the wrong way!. Commented Feb 19, 2022 at 4:57
  • how about params.permit(:name, :body, :element) ? Commented Feb 19, 2022 at 4:59
  • I don't think this will work! It will return unpermitted parameters exception for all fields. Commented Feb 19, 2022 at 5:02
  • I’m sorry that I can’t help you with this, but I recommend you to change the attr_accessor :element to attr_accessor :elements so that your team work or other people who read your question will not misunderstanding Commented Feb 19, 2022 at 5:05

2 Answers 2

8

You haven't mentioned the version of rails you are using but, :elements => [] does not work because elements is a ruby hash and not an array

on rails 5.1+ you can use

params.require(:category).permit(:name, :body, :elements => {}) 
8
  • Great, I was missing this. Thanks Commented Feb 19, 2022 at 5:51
  • 2
    This isn't quite correct. Nested parameters are actually instances of ActionController::Parameters and parameters whitelisting isn't some some case of an equity check.
    – max
    Commented Feb 19, 2022 at 16:19
  • @max I never claimed it was an equality check. Just showing the OP how to fix their problem.
    – Shaunak
    Commented Aug 9, 2022 at 3:37
  • Is it possible to specify the permitted hash keys inside elements?
    – Pioz
    Commented May 4, 2023 at 13:04
  • is it safe todo? since its accept whatever hash the elements have?
    – buncis
    Commented May 10, 2023 at 9:11
0

A lot of confusion going on here besides the element / elements naming issue - pick one and stick with it.

If you want to pass an array as FormData in Rack applications you need to use keys with empty brackets:

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"]}   

If you place any sort of value in the brackets it will be parsed as a hash instead:

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"}}    

When whitelisting an empty array will permit an array of 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> 

When whitelisting hashes you pass an array of symbols which represent the keys you want to permit:

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>

You can also permit a hash with arbitrary keys by passing an empty hash:

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

This is a somewhat dangerous operation and should be done with care.

1
  • it's kinda confusing, so in strong parameters the bracket doesn't mean the parameters comes in array/multiples, to make ruby/rails know that your parameters is array/multiple you need to add bracket with index into it more read here
    – buncis
    Commented May 10, 2023 at 13:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.