Rails 4.0 Strong Parameters Nested Attributes With a Key That Points to a Hash

Rails 4.0 Strong Parameters nested attributes with a key that points to a hash

My other answer was mostly wrong - new answer.

in your params hash, :filename is not associated with another hash, it is associated with an ActiveDispatch::Http::UploadedFile object. Your last code line:

def screenshot_params
params.require(:screenshot).permit(:title, assets_attributes: :filename)

is actually correct, however, the filename attribute is not being allowed since it is not one of the permitted scalar types. If you open up a console, and initialize a params object in this shape:

params = ActionController::Parameters.new screenshot: { title: "afa", assets_attributes: {"0" => {filename: 'a string'}}}

and then run it against your last line:

p = params.require(:screenshot).permit(:title, assets_attributes: :filename)
# => {"title" => "afa", "assets_attributes"=>{"0"=>{"filename"=>"abc"}}}

However, if you do the same against a params hash with the uploaded file, you get

upload = ActionDispatch::Http::UplaodedFile.new tempfile: StringIO.new("abc"), filename: "abc"
params = ActionController::Parameters.new screenshot: { title: "afa", assets_attributes: {"0" => {filename: upload}}}
p = params.require(:screenshot).permit(:title, assets_attributes: :filename)

# => {"title" => "afa", "assets_attributes"=>{"0"=>{}}}

So, it is probably worth a bug or pull request to Rails, and in the meantime, you will have to directly access the filename parameter using the raw params object:

params[:screenshot][:assets_attributes]["0"][:filename]

Strong parameters with nested hash

It's done with syntax like:

answers_attributes: [:id, :content]

The problem is the keys you are using in the answers_attributes. They are expected to be the ids of the answers_attributes or in the case of new records 0.

Changing these gives your expected outcome:

json = {
id: 1,
answers_attributes: {
"1": { id: "", content: "Hi" },
"2": { id: "", content: "Ho" }
}
}

params = ActionController::Parameters.new(json)

params.permit(:id, answers_attributes:[:id, :content])
=> {"id"=>1, "answers_attributes"=>{"1"=>{"id"=>"", "content"=>"Hi"}, "2"=>{"id"=>"", "content"=>"Ho"}}}

Edit: It appears that 0 is not the only key, I mean what if you have two new records. I use nested_form and it appears to use a very long random number.

How can I store random nested variables with strong params methods in Rails?

ActionController::Parameters does not have a "wildcard" syntax to allow any nested hash keys. But it does have #permit! which is an acknowledgement that strong parameters is not the solution for every possible problem.

permit! completely circumvents whitelisting by setting the permitted attribute on the ActionController::Parameters instance.

It will also set the permitted attribute on any nested instances of ActionController::Parameters - ie nested hashes in the parameters.

This is a very sharp tool which should be used with care.

In this case you might want to just use it on the nested attributes:

params.permit(:name, :age).merge(
books: params.dup.permit!.fetch(:books, [])
)

Rails 4: strong parameter with variable key hash

The strong params method is just ruby, you don't have to provide a literal hash as the argument to permit, you can provide a hash that you create based on the "iter_" keys present in params:

iter_array = [ :employee_id, :signed, :consults ]
p = params.require(:consult_stat)
p.permit(
:revenue,
:weeks,
:weeks_paid_up_front,
:additional_weeks,
:extensions,
:paid_in_full,
Hash[p.keys.grep(/^iter_\d+$/).map {|k| [k.to_sym, iter_array] }]
)

Rails - Strong Parameters - Nested Objects

As odd as it sound when you want to permit nested attributes you do specify the attributes of nested object within an array. In your case it would be

Update as suggested by @RafaelOliveira

params.require(:measurement)
.permit(:name, :groundtruth => [:type, :coordinates => []])

On the other hand if you want nested of multiple objects then you wrap it inside a hash… like this

params.require(:foo).permit(:bar, {:baz => [:x, :y]})


Rails actually have pretty good documentation on this: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit

For further clarification, you could look at the implementation of permit and strong_parameters itself: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb#L246-L247

How to make an optional strong parameters key but filter nested params?

What about:

params.require(:item).permit! if params[:item]

You cannot require an optional parameter. That is contradictory.

Edit: as mtjhax mentioned in his comment, there is advice from here to use fetch instead: params.fetch(:item, {}).permit!

Strong parameters and Nested Routes - Rails 4.0

You need to change the order of the arguments passed in to permit to fix the syntax error:

def create_new_api_key
params.require(:api_key).permit(:api_key, user_attributes: [:id])
end


Related Topics



Leave a reply



Submit