This is the community continued version of
protected_attributesfor Rails 5+. I recommend you only use it to support legacy portions of your application that you do not want to upgrade. The Rails team dropped this feature and switched tostrong_parametersbecause of security issues. However some applications simply cannot be upgraded or security like this is a non-issue. To continue supporting this feature going forward lets continue the work here.
Protect attributes from mass-assignment in Active Record models. This gem adds the class methods attr_accessible and attr_protected to declare white or black lists of attributes.
Add this line to your application's Gemfile:
gem 'protected_attributes_continued'And then execute:
bundle installMass assignment security provides an interface for protecting attributes from end-user injection. This plugin provides two class methods in Active Record classes to control access to their attributes. The attr_protected method takes a list of attributes that will be ignored in mass-assignment.
For example:
attr_protected :adminattr_protected also optionally takes a role option using :as which allows you to define multiple mass-assignment groupings. If no role is defined then attributes will be added to the :default role.
attr_protected :last_login, as: :adminA much better way, because it follows the whitelist-principle, is the attr_accessible method. It is the exact opposite of attr_protected, because it takes a list of attributes that will be mass-assigned if present. Any other attributes will be ignored. This way you won’t forget to protect attributes when adding new ones in the course of development. Here is an example:
attr_accessible :name
attr_accessible :name, :is_admin, as: :adminIf you want to set a protected attribute, you will have to assign it individually:
params[:user] # => {name: "owned", is_admin: true}
@user = User.new(params[:user])
@user.is_admin # => false, not mass-assigned
@user.is_admin = true
@user.is_admin # => trueWhen assigning attributes in Active Record using attributes= the :default role will be used. To assign attributes using different roles you should use assign_attributes which accepts an optional :as options parameter. If no :as option is provided then the :default role will be used.
You can also bypass mass-assignment security by using the :without_protection option. Here is an example:
@user = User.new
@user.assign_attributes(name: 'Josh', is_admin: true)
@user.name # => Josh
@user.is_admin # => false
@user.assign_attributes({ name: 'Josh', is_admin: true }, as: :admin)
@user.name # => Josh
@user.is_admin # => true
@user.assign_attributes({ name: 'Josh', is_admin: true }, without_protection: true)
@user.name # => Josh
@user.is_admin # => trueIn a similar way, new, create, create!, update_attributes and update_attributes! methods all respect mass-assignment security and accept either :as or :without_protection options. For example:
@user = User.new({ name: 'Sebastian', is_admin: true }, as: :admin)
@user.name # => Sebastian
@user.is_admin # => true
@user = User.create({ name: 'Sebastian', is_admin: true }, without_protection: true)
@user.name # => Sebastian
@user.is_admin # => trueBy default the gem will use the strong parameters protection when assigning attribute, unless your model has attr_accessible or attr_protected calls.
By default, attributes in the params hash which are not allowed to be updated are just ignored. If you prefer an exception to be raised configure:
config.active_record.mass_assignment_sanitizer = :strictAny protected attributes violation raises ActiveModel::MassAssignmentSecurity::Error then.
We use the appraisal gem for testing multiple versions of Rails. Please use the following steps to test using appraisal.
bundle exec appraisal installbundle exec appraisal rake test
Created & Maintained by Weston Ganger - @westonganger
Originally forked from the dead/unmaintained protected_attributes gem by the Rails team.
While I do utilize this gem in some legacy projects. The latest approach I have adopted is similar to this gem but only utilizes Rails built-in strong_params which is a much more future proof way of doing things. The following is an example implementation.
### Model
class Post < ActiveRecord::Base
def self.strong_params(params)
params.permit(:post).permit(:name, :content, :published_at)
end
end
### Controller
class PostsController < ApplicationController
def create
@post = Post.new(Post.strong_params(params))
@post.save
respond_with @post
end
def update
@post = Post.find(params[:id])
@post.update(Post.strong_params(params))
respond_with @post
end
end