This is the community continued version of
protected_attributesfor Rails 5+. The Rails team dropped this feature and switched tostrong_parameters. However some applications simply cannot be upgraded or the reduced granularity in params management is a non-issue. To continue supporting this feature going forward we continue the work here.
This gem only supports Rails 5.0 to Rails 6.1. Starting in Rails 7.0 some API's have been changed and this gem will not be updated to support it, please transition to strong params or the suggested alternative approach at the bottom of the readme.
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.
For quicker feedback during gem development or debugging feel free to use the provided rake console task. It is defined within the Rakefile.
We test multiple versions of Rails using the appraisal gem. 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
has_many :comments
accepts_nested_attributes_for :comments, allow_destroy: true
def self.strong_params(params)
params.permit(:post).permit(*PERMITTED_ATTRIBUTES)
end
PERMITTED_ATTRIBUTES = [
:id,
:name,
:content,
:published_at,
{
comments_attributes: Comment::PERMITTED_ATTRIBUTES,
}
].freeze
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