The following blog post contains material either currently found or soon to be incorporated into my new book, "Easy Active Record for Rails Developers". Among many other topics, you'll learn about model generation, migrations, validations, associations, scopes, joins, includes, forms integration, nested forms, and model testing with RSpec and FactoryGirl. The book is now available, head over to this website's home page to learn more.
Longtime Rails users are undoubtedly familiar with the
attr_accessible macro. It is used in conjunction with a Rails model to explicitly identify the model attributes that can be set using mass-assignment. For instance, to identify the
zip attributes as mass-assignable, you would set
attr_accessible within the
Location model like this:
class Location attr_accessible :name, :description, :city, :zip end
attr_accessible set like so, I can now conveniently mass-assign these attributes:
location = Location.new( :name => 'Arcade Legacy', :description => 'Offers more than one dozen arcade classics!', :city => 'Cincinnati', :zip => '45240')
zip parameters coming from a properly configured form, assignment is even easier:
location = Location.new(params[:location])
In either case, both approaches are preferable to manually setting each attribute like so:
location = Location.new location.name = 'Arcade Legacy' location.description = 'Offers more than one dozen arcade classics!' location.city = 'Cincinnati' location.zip = '45240'
As is demonstrated by these examples, the
attr_accessible macro is indeed useful. But what if the model included an additional Boolean attribute called
approved that an administrator would use to confirm the submitted arcade was indeed worth of inclusion? If you added
approved to the
attr_accessible list, then a cunning arcade operator could inject
params[:location][:approved] into the POSTed form and bypass the official approval process. At the same time, opting to omit the
approved attribute from the
attr_accessible declaration means you’ll need to resort to a less efficient solution for coding the administrative interface’s
update actions differently (notably, using the latter approach involving manually setting each attribute separately).
Enter Rails 4 and Strong Parameters
Ever the pragmatists, the Rails development team removed this inconsistency in Rails 4, deprecating
attr_accessible (and its’ sibling
attr_protected) in preference of a new feature known as strong parameters. This approach moves the burden of whitelisting to the controller, allowing you to whitelist attributes within the context in which they will be used, rather than requiring a global whitelisting within the model.
To use strong parameters you’ll typically want to define a private method within the desired controller:
class LocationController < ActionController::Base def new end def create end def edit end def update end private def location_params params.require(:location).permit(:name, :description, :city, :zip) end end
params.require method identifies the required parameter, in this case
permit method identifies the list of allowed parameter keys, in this case
zip. With the
location_params method defined, you can use it both within your
update methods. I’ll next create simplified
update methods to demonstrate use of the private
class LocationController < ActionController::Base def create @location = Location.create(location_params) end def update location = Location.find(params[:id]) location = Location.update_attributes!(location_params) redirect_to location end private def location_params params.require(:location).permit(:name, :description, :city, :zip) end end
So returning to our original problem, how would you provide the administration controller with the ability to mass-assign the
approved attribute? That’s right, you’ll just add a customized version of the
location_params method to the appropriate controller:
def location_params params.require(:location).permit(:name, :description, :city, :zip, :approved) end
Once in place, you’re free to code the
update methods in the same manner as above, foregoing the need for any additional customized coding.
In a later post I’ll talk about advanced strong parameters features, such as the ability to whitelist nested parameters.
Like what you read? There’s plenty more where this came from in my new book, “Easy Active Record for Rails Developers”!