I'm submitting a form with 2-4 objects at once, depending on how many the parent has. I realize that this is probably unconventional, but I really wanted the user to be able to edit all of the objects at once on one form. On my form, I'm doing:
<%= simple_fields_for "derps[]", derp do |f| %>
<% end %>
Then I'm doing this in the controller:
def update
@derps = []
@rejects = []
derps_params.each do |key, hash|
derp = Derp.find(key)
derp.assign_attributes(hash)
@rejects << derp unless derp.save
end
if @rejects.empty?
redirect_to @parent, flash: {success: 'Derps were successfully updated.'}
else
@derps = @rejects
render :edit
end
end
Lets say there are two objects - the params are coming through as:
"derps"=>{"1"=>{"attribute"=>"39", "another_attribute"=>"serp", "a_third_attribute"=>"yerp"}, "2"=>{"attribute"=>"30", "another_attribute"=>"49", }}
I had this working in Rails 3 without strong params. I'm upgrading to rails 4 and I'm struggling with how to get this working - I keep getting "Unpermitted parameters: 1, 2"
I'm assuming I need to do something like:
def mashes_params
params.require(:derps).permit(
id: []
or
def mashes_params
params.require(:derps).permit(
:id,
Something along those lines, but I've tried it every way I can think of without luck.
Any ideas here?
I've found that the command line is immensely helpful for debugging Strong Parameters in Rails 4. Here's how I tested your problem in the console:
rails c # From within your project directory, short for 'rails console'
params = ActionController::Parameters.new( { derps: { 1 => { attribute: 39, another_attribute: "serp" }, 2 => { attribute: 30, another_attribute: 49 } } } )
params # To make sure that the object looks the same
permitted = params.require( :derps ).permit( 1 => [ :attribute, :another_attribute ], 2 => [ :attribute, :another_attribute ] )
permitted # To see what you'd get back in your controller
Hopefully with this tool, you'll be able to debug anything that my answer didn't provide more easily than trial and error.
Final Edit (hopefully):
Had to rethink this from the ground up. I came to the conclusion: Since :id works as a wildcard, but is not allowed as the key of the hash, why not always make the keys 1-4, so I can whitelist them explicitly, then get the ID from a key-value in the hash, much like is done in traditional form nesting? Thats how I ended up solving it. Here's the final implementation that I have working:
<% i = @parent.derps.index(derp) + 1 %>
<%= simple_fields_for "derps[#{i}]", derp do |f| %>
<%= f.hidden_field :id, value: derp.id %>
<%= render "rest_of_the_fields" %>
<% end %>
Then in the controller:
def update
@derps = []
@rejects = []
derp_params.each do |key, hash|
derp = Derp.find(hash.delete("id"))
derp.assign_attributes(hash)
@rejects << derp unless derp.save
end
if @rejects.empty?
redirect_to @parent, flash: {success: "Derps updated successfully."}
else
@derps = @rejects
render :edit
end
end
Then here are the strong params:
def derp_params
p = [:id, :attribute_1, :another_attribute, ...]
params.require(:derps).permit(
"1" => p, "2" => p, "3" => p, "4" => p
)
end
Phew. Hope this helps someone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With