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
Heroku Not Sending Email With Gmail Smtp
Why Are Methods in Ruby Documentation Preceded by a Hash Sign
Fibonacci Sequence in Ruby (Recursion)
How to Format the Value Shown in a Rails Edit Field
Ruby on Rails - Unable to Convert "\X89" from Ascii-8Bit to Utf-8 for Xxx/Xxxx/Xxxx
Cache Resources Exhausted Imagemagick
In Ruby Why Won't 'Foo = True Unless Defined(Foo)' Make the Assignment
Ruby: How to Install a Specific Version of a Ruby Gem
Imagemagick - "Core_Rl_Magick_.Dll Not Found" or How to Install Rmagick on Windows With Ruby 1.9.2
When to Use Each Method of Launching a Subprocess in Ruby
How to Sort an Array in Ruby to a Particular Order
Ruby: Class Instance Variables VS Instance Variables
Mavericks, Rbenv, Your Ruby Version Is 2.0.0, But Your Gemfile Specified 2.1.1