Recently I stumbled onto the ParamsWrapper system inside of Rails. It’s a convenient system that allows form data to be submitted without specifying the root object. For example, if you are creating a new post you can specify the name using either name=”name” or name=”post[name]”. Either way you can access the attribute using params[:post][:name].
Most of the time the system works perfectly without modification. It uses the model represented by the controller’s attr_accessor definition to determine which attributes work. However if you are not using the rails preferred naming scheme this system may no longer work as expected.
For example, let’s create a User model and a RegistrationController
class User < ActiveRecord::Base attr_accessor :name, :email end class RegistrationController < ApplicationController def create User.create params[:user] end end
And a form to create the user
<%= form_for @user do %> <input name="name" type="text" /> <input name="email" type="email" /> <% end %>
Now since we can usually rely on ParamsWrapper the above code would work. However since we’ve named our controller registrations we can no longer guarantee the users parameters will exist in params[:user]. We can however fix this by calling the wrap_parameters method on the controller.
class RegistrationController < ApplicationController wrap_parameters User def create User.create params[:user] end end
Take notice we specify the model using the class and not a symbol. By using the class the models class will be used to determine what attributes to place in the params[:user] hash. If a symbol is specified all attributes passed in will be placed into the hash.