Rails duplicated the parameters inside the resource

All we need is an easy explanation of the problem, so here it is.

I am using the Angular Resource and I don’t understand why Rails duplicated the parameters and put it inside the resource name. I just need to understand why this is happening.

// post data
{"title":"asdsad"}

// rails parameters 
Parameters: {"title"=>"asdsad", "presentation"=>{"title"=>"asdsad"}}

Duplicate because welcome to Stackoverflow where you need 50 points to comments so this happen. I really so sorry: AngularJS $resource sending out an extra "registration" hash?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

..if you’ve turned on config.wrap_parameters in your initializer [check the file
config/initializers/wrap_parameters.rb] or [you] are calling
wrap_parameters() in your controller…the parameters will be cloned and
wrapped in the key according to your controller’s name by default.

http://guides.rubyonrails.org/action_controller_overview.html#parameters
http://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html

In other words, what you are seeing is the default way rails enters things in the params hash.

Method 2

I had the same question but I hadn’t understood the problem and needed a different solution.

In my passwords controller (for enabling password reset via email), my parameters looked like this:

{"email"=>"[email protected]", "code"=>"123", "password"=>"[FILTERED]", "password"=>{"email"=>"[email protected]", "code"=>"123", "password"=>"[FILTERED]"}}

I thought, “why are my params duplicated inside of password“, not realizing that the outer password was coming from the resource name. (Thanks, 7stud!) But if I added wrap_parameters false at the top of my controller to flatten out the params, then I couldn’t use the ‘require/permit’ pattern for strong params:

#passwords_controller.rb
...
private
def forgot_password_params
    params.require(:password).permit(:email, :password, :code)
end

To make this more legible, I used wrap_parameters to rename the outer password ref in the params. The code:

#passwords_controller.rb
wrap_parameters "reset" 
...
private
def forgot_password_params
    params.require(:reset).permit(:email, :password, :code)
end

and the resulting params: {"email"=>"[email protected]", "code"=>"123", "password"=>"[FILTERED]", "reset"=>{"email"=>"[email protected]", "code"=>"123", "password"=>"[FILTERED]"}}

I then immediately ran into a related issue where for an in-app password reset, I passed in newPassword from my form but it was not in my params. By default, params only include attributes from the model. wrap_parameters let me fix this as well:

#users_controller.rb
wrap_parameters :user, include: [:username, :email, :password, :newPassword]

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply