I have an array of users I want to save in my database. An example when shown in the console after a POST is made:
"users"=>[{"name"=>"Job", "email"=>"*****"}, {"name"=>"Ed", "email"=>"****"}]
No nested attributes going on here. How to format strong params for this?
def user_params
params.fetch(:user, {}).permit(:name, :email, ...)
end
This may work for saving a single user but I'm passing an array of users. I'm currently storing the user in a "dirty" manner:
users = params[:users]
users.each do |user|
User.create(name: user[:name], email: user[:email])
end
I'd like to refactor and do something like:
User.create(user_params)
To permit a param key containing an array of hashes you pass the name as the key and an array of permitted attributes:
def user_params
params.permit(users: [:name, :email, ...])
.fetch(:users, [])
end
The output will be an array of ActionController::Parameters instances or an empty array if the key is not present:
[#<ActionController::Parameters {"name"=>"Job", "email"=>"*****"} permitted: true>,
#<ActionController::Parameters {"name"=>"Ed", "email"=>"****"} permitted: true>]
Related
I'm having trouble with parameters in an app upgraded from 4.2 to 5.1. I have permitted my parameters, but as the documentation states, I'm getting back an object for my hash array, but can't seem to access the values of it. How can I just get the value of this object?
{"_method"=>"delete", "authenticity_token"=>"Z6ZqriiuXu6ODDqhGgocGiaN12rjKD6pUB6n/2v+CABZDAjwLzwczsMM3nM8f0PI0nww43o5mlC35HK+9PVa8w==",
"domain_name"=>"test.testmodule2.com.",
"hosted_zone_id"=>"/hostedzone/XXXXXXXXXX",
"ttl"=>"3600",
"type"=>"A",
"value"=>[{"value"=>"1.1.1.1"}],
"id"=>"/hostedzone/XXXXXXXXXX"}
def record_params
params.permit!([:hosted_zone_id, :domain_name, :type, :ttl, :alias, :value]).to_h!
end
def destroy
value = params[:value]
# returns [<ActionController::Parameters {"value"=>"1.1.1.1"} permitted: true>]
# would like it to return [{"value"=>"1.1.1.1"}]
end
If that hash is the value of params[:value], then access the value key inside, like:
params[:value] = {
"_method"=>"delete",
"authenticity_token"=>"...",
"domain_name"=>"test.testmodule2.com.",
"hosted_zone_id"=>"/hostedzone/XXXXXXXXXX",
"ttl"=>"3600",
"type"=>"A",
"value"=>[{"value"=>"1.1.1.1"}],
"id"=>"/hostedzone/XXXXXXXXXX"
}
params['value']['value'][0]['value']
# => "1.1.1.1"
params['value']['value'][0].keys
# => ["value"]
I get params like this: Parameters: {"utf8"=>"✓", "events"=>{"363"=>{"name"=>"3"}}, "new_events"=>[{"name"=>"1"}, {"name"=>"2"}], "date"=>"2016-11-01"}
What I would like to do is create Events from new_events array of hashes, but it doesn's let me because it neets to be sanitized for mass assignment.
This is how event_params looks like:
def event_params
params.require(:events).permit(:id, :name, :start_time, :user_id)
end
This setup is because I want to update and/or create new records when I press submit.
The current way I do this is
params[:new_events].each_with_object({}) do |e|
Event.create(name: e[:name], user_id: current_user.id, start_time: params[:date])
end
But Im not sure it's the correct way to do it
You should be able to sanitize the array of parameters:
params.require(:events).permit(new_events: [:name])
Event.create(params[:new_events] do |new_event|
new_event.user = current_user
end
But note that you'll have to loop over the objects anyway, so it doesn't make much of a difference. You may want to just do the loop with Event.new and validate them as a group:
events = Event.new(params[:new_events]) do |new_event|
new_event.user = current_user
...
end
if events.any?(&:invalid?)
[error handling]
else
events.save!
I have this:
def some_params
params.require(:person).permit(:name, :pass)
These params are under the key "person" in "params". How can I add a key from the top level of "params" to the list of permitted params? In total it should result into 3 keys of permitted params.
Just add other call to the method require like:
params = ActionController::Parameters.new({
key1: 1,
person: {
name: 'Francesco',
pass: 'pass'
}
})
params.permit(:key1, {:person => [:name, :pass]})
Check the docs at: https://github.com/rails/strong_parameters#require-multiple-parameters
Require Multiple Parameters
If you want to make sure that multiple keys are present in a params
hash, you can call the method twice:
params.require(:token)
params.require(:post).permit(:title)
I have the follow strong_params statement:
def product_grid_params
params.require(:product_grid).permit(:name,
product_grid_locations_attributes: [:id, :grid_index, :item_id, :item_type, :short_name, :long_name]
).merge({ venue_id: params[:venue_id] })
end
But my params and product_grid_params look like this:
(byebug) params
{"product_grid"=>{"product_grid_locations_attributes"=>[{"id"=>"5560d1f7a15a416719000007", "short_name"=>"shrt", "long_name"=>"Whiskey Ginger", "grid_index"=>73, "item_type"=>"product", "item_id"=>"9b97aa28-1349-4f60-a359-3907c8ac9a74"}]}, "id"=>"5560d1f7a15a416719000006", "venue_id"=>"5560d1f7a15a416719000005", "format"=>"json", "controller"=>"api/v2/manager/product_grids", "action"=>"update"}
(byebug) product_grid_params
{"product_grid_locations_attributes"=>[{"grid_index"=>73, "item_id"=>"9b97aa28-1349-4f60-a359-3907c8ac9a74", "item_type"=>"product", "short_name"=>"shrt", "long_name"=>"Whiskey Ginger"}], "venue_id"=>"5560d1f7a15a416719000005"}
You'll notice that in the params, the product_grid_location's id is present, but it gets filtered out in product_grid_params. What gives? I need that id there to update nested attributes.
Looks like this was because of an issue with Mongoid. The id I was passing in was a Moped::BSON::ObjectId, which strong_params refused to parse. I converted it to a string and everything was fine after that:
params[:product_grid][:product_grid_locations_attributes].each { |location| location[:id] = location[:id].to_str }
I would like to save the params from the form submitted into a hash called: hash_options which corresponds to a field in my table.
How do I store the hash of: hash_options as the value for: hash_fields ?
hash_fields is a text field and I am trying to store hash_options in this row as a plain hash.
def person_params
hash_options = {age: params['person']['age'], location: params['person']['location'], gender: params['person']['gender']}
params.require(:person).permit(:first_name, :last_name, :owner, hash_fields: [hash_options])
end
Side question: How does the model access and store the params?
In order to be able to save the hash as is to the database you have a couple of options:
If you are using MongoDB(mongoid) you can just define it as a hash type field in your model with:
field options_hash, type: Hash
You can use postgresql HStore to save schemaless data into that column which enables you to save the hash into the column and work with it as a Hash.
As for the params part there is no need to include it in the permit call, you can just do:
model = Model.new(person_params) do |m|
m.options_hash = hash_options
end
model.save