The basic security reason for the existence of both strong parameters and attr_accessible is that there are certain attributes in the model that should not be allow to be changed unless it is the explicit intention of your code.
The slight difference between them is the perspective form which they do their jobs.
StrongParameters focus on the use case: each controller's action can be fine tuned to allow or disallow certain parameters, taking in consideration any condition. Total flexibility.
attr_accessible takes a different perspective. Instead of focusing on the use case, it focus on roles. So for example, depending on the role of the user certain attributes can be changed or not.
The way to use StrongParameters is to apply the require
and permit
keywords on the param hash.
require
states that a key must be present on the params hash. require
will raise an exception if there is not such a key.
permit
states that a field is allowed. Any key that is not allowed will be removed from the hash and hence will not be passed to the model by means of mass-assignment.
Model
class League
attr_protected :final_price # Nobody can mass-assign the final price
attr_accessible :winner_name, :as => :jury
end
And the controller
class LeaguesController < ApplicationController
These two actions use StrongParameters
# A common user can create a league
def create
league = League.new(league_params)
league.final_price = 1000
league.save
redirect_to(league)
end
# But only the admin can publish a league
def publish_league
league = League.find(params[:id]
league.update_attributes(league_params_as_admin)
end
This one uses attr_accessible
def publish_the_winner
league = League.find(params[:id]
# We would expect the current_user.role to return :jury.
league.assign_attributes(params[:league], :as => current_user.role)
end
private
def league_params
params.require(:league).permit(:name)
end
def league_params_as_admin
params.require(:league).permit(:name, :status)
end
end
In my experience:
Use the flexibility of Strong Parameters to fine tune what attributes can be mass-assigned in each of your controllers.
Use the omnipresence of attr_accesible to make sure that certain attributes can not be mass-assigned no matter what. For example, in a Resque Task you may pass user input as a parameter. You would check that some attributes are not mass-assigned using attr_accesible.
More info:
http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html
https://github.com/rails/strong_parameters