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.


The Rails team has always been careful to take precautions that help to prevent malicious attackers from compromising an application’s data. One of the most visible historical protections involved using the attr_accessible method within a model to identify which model attributes could be passed into methods like new and update_attributes for mass assignment. For instance when using Rails 3 if you only wanted to allow the Location model’s name, street, and city attributes to be updatable via mass assignment you would define attr_accessible like so:

class Location < ActiveRecord::Base

  attr_accessible :name, :street, :city

  ...

end

By giving the developer control over which parameters were whitelisted for such purposes, the presumption was that data could be better protected by eliminating the possibility an attacker could modify a sensitive attribute by injecting it into a form body. This worked great but had a significant drawback, because attr_accessible is an all-or-nothing proposition. The developer couldn’t for instance change the model requirements when working within an administration console, because attr_accessible could only be defined once. This changed with Rails 4, thanks to a new approach for managing mass assignment behavior. Known as strong parameters, the task of defining which parameters are available for mass assignment has been moved out of the model and into the controllers, allowing developers to define mass assignment behavior according to action.

Consider a simplified version of the Game model that consisted of the attributes name, description and active, the latter determining whether the game was displayed on the site. If the site were community-driven you are probably fine with name and description being updated but want to restrict any updates to active to administrators. Therefore you would use the strong parameters approach to define a method in the (presumably) Games controller that looks like this:

class GamesController < ApplicationController

  ...

  def game_params

    params.require(:game).permit(:name, :description)

  end

This method would then be passed into the update action’s update method:

def update

  @game = Game.find(params[:id])

  if @game.update(game_params)
    ...
  end

end

Meanwhile, in a secure administration console you might wish to mass-update additional attributes. In the appropriate administration controller you could define another method that looks like this:

def game_params

  params.require(:game).permit(:name, :description, :active)

end

This would give the administrator the ability to update the active attribute right alongside name and description using mass-assignment.

If one of your attributes accepts an array (such as is the case when working with certain types of associations; more on this topic in Chapter 4), you’ll need to define that attribute a bit differently in the permit method. For instance the following example is a variation of the same strong parameters method used in ArcadeNomad’s Location controller, because we need to pass along an array of game IDs when creating a new location:

def location_params

  params.require(:location).permit(:name, :description, :category_id, :game_ids => [])

end

Comments