Merge pull request #455 from joshk/mass_assignment_roles

Renamed mass-assignment scopes to roles
This commit is contained in:
José Valim 2011-05-08 08:19:38 -07:00
commit f69be6ae8f
6 changed files with 64 additions and 64 deletions

@ -35,17 +35,17 @@ module MassAssignmentSecurity
# protected # protected
# #
# def account_params # def account_params
# scope = admin ? :admin : :default # role = admin ? :admin : :default
# sanitize_for_mass_assignment(params[:account], scope) # sanitize_for_mass_assignment(params[:account], role)
# end # end
# #
# end # end
# #
module ClassMethods module ClassMethods
# Attributes named in this macro are protected from mass-assignment # Attributes named in this macro are protected from mass-assignment
# whenever attributes are sanitized before assignment. A scope for the # whenever attributes are sanitized before assignment. A role for the
# attributes is optional, if no scope is provided then :default is used. # attributes is optional, if no role is provided then :default is used.
# A scope can be defined by using the :as option. # A role can be defined by using the :as option.
# #
# Mass-assignment to these attributes will simply be ignored, to assign # Mass-assignment to these attributes will simply be ignored, to assign
# to them you can use direct writer methods. This is meant to protect # to them you can use direct writer methods. This is meant to protect
@ -67,7 +67,7 @@ module ClassMethods
# end # end
# end # end
# #
# When using a :default scope : # When using the :default role :
# #
# customer = Customer.new # customer = Customer.new
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default) # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default)
@ -78,7 +78,7 @@ module ClassMethods
# customer.credit_rating = "Average" # customer.credit_rating = "Average"
# customer.credit_rating # => "Average" # customer.credit_rating # => "Average"
# #
# And using the :admin scope : # And using the :admin role :
# #
# customer = Customer.new # customer = Customer.new
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin) # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin)
@ -93,10 +93,10 @@ module ClassMethods
# to sanitize attributes won't provide sufficient protection. # to sanitize attributes won't provide sufficient protection.
def attr_protected(*args) def attr_protected(*args)
options = args.extract_options! options = args.extract_options!
scope = options[:as] || :default role = options[:as] || :default
self._protected_attributes = protected_attributes_configs.dup self._protected_attributes = protected_attributes_configs.dup
self._protected_attributes[scope] = self.protected_attributes(scope) + args self._protected_attributes[role] = self.protected_attributes(role) + args
self._active_authorizer = self._protected_attributes self._active_authorizer = self._protected_attributes
end end
@ -104,8 +104,8 @@ def attr_protected(*args)
# Specifies a white list of model attributes that can be set via # Specifies a white list of model attributes that can be set via
# mass-assignment. # mass-assignment.
# #
# Like +attr_protected+, a scope for the attributes is optional, # Like +attr_protected+, a role for the attributes is optional,
# if no scope is provided then :default is used. A scope can be defined by # if no role is provided then :default is used. A role can be defined by
# using the :as option. # using the :as option.
# #
# This is the opposite of the +attr_protected+ macro: Mass-assignment # This is the opposite of the +attr_protected+ macro: Mass-assignment
@ -131,7 +131,7 @@ def attr_protected(*args)
# end # end
# end # end
# #
# When using a :default scope : # When using the :default role :
# #
# customer = Customer.new # customer = Customer.new
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default) # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :default)
@ -141,7 +141,7 @@ def attr_protected(*args)
# customer.credit_rating = "Average" # customer.credit_rating = "Average"
# customer.credit_rating # => "Average" # customer.credit_rating # => "Average"
# #
# And using the :admin scope : # And using the :admin role :
# #
# customer = Customer.new # customer = Customer.new
# customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin) # customer.assign_attributes({ "name" => "David", "credit_rating" => "Excellent", :last_login => 1.day.ago }, :as => :admin)
@ -152,20 +152,20 @@ def attr_protected(*args)
# to sanitize attributes won't provide sufficient protection. # to sanitize attributes won't provide sufficient protection.
def attr_accessible(*args) def attr_accessible(*args)
options = args.extract_options! options = args.extract_options!
scope = options[:as] || :default role = options[:as] || :default
self._accessible_attributes = accessible_attributes_configs.dup self._accessible_attributes = accessible_attributes_configs.dup
self._accessible_attributes[scope] = self.accessible_attributes(scope) + args self._accessible_attributes[role] = self.accessible_attributes(role) + args
self._active_authorizer = self._accessible_attributes self._active_authorizer = self._accessible_attributes
end end
def protected_attributes(scope = :default) def protected_attributes(role = :default)
protected_attributes_configs[scope] protected_attributes_configs[role]
end end
def accessible_attributes(scope = :default) def accessible_attributes(role = :default)
accessible_attributes_configs[scope] accessible_attributes_configs[role]
end end
def active_authorizers def active_authorizers
@ -198,12 +198,12 @@ def accessible_attributes_configs
protected protected
def sanitize_for_mass_assignment(attributes, scope = :default) def sanitize_for_mass_assignment(attributes, role = :default)
mass_assignment_authorizer(scope).sanitize(attributes) mass_assignment_authorizer(role).sanitize(attributes)
end end
def mass_assignment_authorizer(scope = :default) def mass_assignment_authorizer(role = :default)
self.class.active_authorizer[scope] self.class.active_authorizer[role]
end end
end end
end end

@ -10,7 +10,7 @@ def test_attribute_protection
assert_equal expected, sanitized assert_equal expected, sanitized
end end
def test_only_moderator_scope_attribute_accessible def test_only_moderator_role_attribute_accessible
user = SpecialUser.new user = SpecialUser.new
expected = { "name" => "John Smith", "email" => "john@smith.com" } expected = { "name" => "John Smith", "email" => "john@smith.com" }
sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true), :moderator) sanitized = user.sanitize_for_mass_assignment(expected.merge("admin" => true), :moderator)
@ -27,7 +27,7 @@ def test_attributes_accessible
assert_equal expected, sanitized assert_equal expected, sanitized
end end
def test_admin_scoped_attributes_accessible def test_attributes_accessible_with_admin_role
user = Person.new user = Person.new
expected = { "name" => "John Smith", "email" => "john@smith.com", "admin" => true } expected = { "name" => "John Smith", "email" => "john@smith.com", "admin" => true }
sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true), :admin) sanitized = user.sanitize_for_mass_assignment(expected.merge("super_powers" => true), :admin)

@ -482,7 +482,7 @@ def find_by_sql(sql, binds = [])
# # Create a single new object # # Create a single new object
# User.create(:first_name => 'Jamie') # User.create(:first_name => 'Jamie')
# #
# # Create a single new object using the :admin mass-assignment security scope # # Create a single new object using the :admin mass-assignment security role
# User.create({ :first_name => 'Jamie', :is_admin => true }, :as => :admin) # User.create({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
# #
# # Create a single new object bypassing mass-assignment security # # Create a single new object bypassing mass-assignment security
@ -1486,7 +1486,7 @@ def encode_quoted_value(value) #:nodoc:
# # Instantiates a single new object # # Instantiates a single new object
# User.new(:first_name => 'Jamie') # User.new(:first_name => 'Jamie')
# #
# # Instantiates a single new object using the :admin mass-assignment security scope # # Instantiates a single new object using the :admin mass-assignment security role
# User.new({ :first_name => 'Jamie', :is_admin => true }, :as => :admin) # User.new({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
# #
# # Instantiates a single new object bypassing mass-assignment security # # Instantiates a single new object bypassing mass-assignment security
@ -1661,8 +1661,8 @@ def attributes=(new_attributes, guard_protected_attributes = nil)
end end
# Allows you to set all the attributes for a particular mass-assignment # Allows you to set all the attributes for a particular mass-assignment
# security scope by passing in a hash of attributes with keys matching # security role by passing in a hash of attributes with keys matching
# the attribute names (which again matches the column names) and the scope # the attribute names (which again matches the column names) and the role
# name using the :as option. # name using the :as option.
# #
# To bypass mass-assignment security you can use the :without_protection => true # To bypass mass-assignment security you can use the :without_protection => true
@ -1689,12 +1689,12 @@ def attributes=(new_attributes, guard_protected_attributes = nil)
# user.is_admin? # => true # user.is_admin? # => true
def assign_attributes(new_attributes, options = {}) def assign_attributes(new_attributes, options = {})
attributes = new_attributes.stringify_keys attributes = new_attributes.stringify_keys
scope = options[:as] || :default role = options[:as] || :default
multi_parameter_attributes = [] multi_parameter_attributes = []
unless options[:without_protection] unless options[:without_protection]
attributes = sanitize_for_mass_assignment(attributes, scope) attributes = sanitize_for_mass_assignment(attributes, role)
end end
attributes.each do |k, v| attributes.each do |k, v|

@ -146,7 +146,7 @@ def update_column(name, value)
# will fail and false will be returned. # will fail and false will be returned.
# #
# When updating model attributes, mass-assignment security protection is respected. # When updating model attributes, mass-assignment security protection is respected.
# If no +:as+ option is supplied then the +:default+ scope will be used. # If no +:as+ option is supplied then the +:default+ role will be used.
# If you want to bypass the protection given by +attr_protected+ and # If you want to bypass the protection given by +attr_protected+ and
# +attr_accessible+ then you can do so using the +:without_protection+ option. # +attr_accessible+ then you can do so using the +:without_protection+ option.
def update_attributes(attributes, options = {}) def update_attributes(attributes, options = {})

@ -87,7 +87,7 @@ def test_mass_assigning_invalid_attribute
end end
end end
def test_assign_attributes_uses_default_scope_when_no_scope_is_provided def test_assign_attributes_uses_default_role_when_no_role_is_provided
p = LoosePerson.new p = LoosePerson.new
p.assign_attributes(attributes_hash) p.assign_attributes(attributes_hash)
@ -101,28 +101,28 @@ def test_assign_attributes_skips_mass_assignment_security_protection_when_withou
assert_all_attributes(p) assert_all_attributes(p)
end end
def test_assign_attributes_with_default_scope_and_attr_protected_attributes def test_assign_attributes_with_default_role_and_attr_protected_attributes
p = LoosePerson.new p = LoosePerson.new
p.assign_attributes(attributes_hash, :as => :default) p.assign_attributes(attributes_hash, :as => :default)
assert_default_attributes(p) assert_default_attributes(p)
end end
def test_assign_attributes_with_admin_scope_and_attr_protected_attributes def test_assign_attributes_with_admin_role_and_attr_protected_attributes
p = LoosePerson.new p = LoosePerson.new
p.assign_attributes(attributes_hash, :as => :admin) p.assign_attributes(attributes_hash, :as => :admin)
assert_admin_attributes(p) assert_admin_attributes(p)
end end
def test_assign_attributes_with_default_scope_and_attr_accessible_attributes def test_assign_attributes_with_default_role_and_attr_accessible_attributes
p = TightPerson.new p = TightPerson.new
p.assign_attributes(attributes_hash, :as => :default) p.assign_attributes(attributes_hash, :as => :default)
assert_default_attributes(p) assert_default_attributes(p)
end end
def test_assign_attributes_with_admin_scope_and_attr_accessible_attributes def test_assign_attributes_with_admin_role_and_attr_accessible_attributes
p = TightPerson.new p = TightPerson.new
p.assign_attributes(attributes_hash, :as => :admin) p.assign_attributes(attributes_hash, :as => :admin)
@ -153,25 +153,25 @@ def test_create_with_attr_protected_attributes
assert_default_attributes(p, true) assert_default_attributes(p, true)
end end
def test_new_with_admin_scope_with_attr_accessible_attributes def test_new_with_admin_role_with_attr_accessible_attributes
p = TightPerson.new(attributes_hash, :as => :admin) p = TightPerson.new(attributes_hash, :as => :admin)
assert_admin_attributes(p) assert_admin_attributes(p)
end end
def test_new_with_admin_scope_with_attr_protected_attributes def test_new_with_admin_role_with_attr_protected_attributes
p = LoosePerson.new(attributes_hash, :as => :admin) p = LoosePerson.new(attributes_hash, :as => :admin)
assert_admin_attributes(p) assert_admin_attributes(p)
end end
def test_create_with_admin_scope_with_attr_accessible_attributes def test_create_with_admin_role_with_attr_accessible_attributes
p = TightPerson.create(attributes_hash, :as => :admin) p = TightPerson.create(attributes_hash, :as => :admin)
assert_admin_attributes(p, true) assert_admin_attributes(p, true)
end end
def test_create_with_admin_scope_with_attr_protected_attributes def test_create_with_admin_role_with_attr_protected_attributes
p = LoosePerson.create(attributes_hash, :as => :admin) p = LoosePerson.create(attributes_hash, :as => :admin)
assert_admin_attributes(p, true) assert_admin_attributes(p, true)
@ -230,12 +230,12 @@ def test_has_one_build_with_attr_accessible_attributes
assert_default_attributes(best_friend) assert_default_attributes(best_friend)
end end
def test_has_one_build_with_admin_scope_with_attr_protected_attributes def test_has_one_build_with_admin_role_with_attr_protected_attributes
best_friend = @person.build_best_friend(attributes_hash, :as => :admin) best_friend = @person.build_best_friend(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend) assert_admin_attributes(best_friend)
end end
def test_has_one_build_with_admin_scope_with_attr_accessible_attributes def test_has_one_build_with_admin_role_with_attr_accessible_attributes
best_friend = @person.build_best_friend(attributes_hash, :as => :admin) best_friend = @person.build_best_friend(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend) assert_admin_attributes(best_friend)
end end
@ -257,12 +257,12 @@ def test_has_one_create_with_attr_accessible_attributes
assert_default_attributes(best_friend, true) assert_default_attributes(best_friend, true)
end end
def test_has_one_create_with_admin_scope_with_attr_protected_attributes def test_has_one_create_with_admin_role_with_attr_protected_attributes
best_friend = @person.create_best_friend(attributes_hash, :as => :admin) best_friend = @person.create_best_friend(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
def test_has_one_create_with_admin_scope_with_attr_accessible_attributes def test_has_one_create_with_admin_role_with_attr_accessible_attributes
best_friend = @person.create_best_friend(attributes_hash, :as => :admin) best_friend = @person.create_best_friend(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
@ -284,12 +284,12 @@ def test_has_one_create_with_bang_with_attr_accessible_attributes
assert_default_attributes(best_friend, true) assert_default_attributes(best_friend, true)
end end
def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes
best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes
best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
@ -318,12 +318,12 @@ def test_has_one_build_with_attr_accessible_attributes
assert_default_attributes(best_friend) assert_default_attributes(best_friend)
end end
def test_has_one_build_with_admin_scope_with_attr_protected_attributes def test_has_one_build_with_admin_role_with_attr_protected_attributes
best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend) assert_admin_attributes(best_friend)
end end
def test_has_one_build_with_admin_scope_with_attr_accessible_attributes def test_has_one_build_with_admin_role_with_attr_accessible_attributes
best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend) assert_admin_attributes(best_friend)
end end
@ -345,12 +345,12 @@ def test_has_one_create_with_attr_accessible_attributes
assert_default_attributes(best_friend, true) assert_default_attributes(best_friend, true)
end end
def test_has_one_create_with_admin_scope_with_attr_protected_attributes def test_has_one_create_with_admin_role_with_attr_protected_attributes
best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
def test_has_one_create_with_admin_scope_with_attr_accessible_attributes def test_has_one_create_with_admin_role_with_attr_accessible_attributes
best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
@ -372,12 +372,12 @@ def test_has_one_create_with_bang_with_attr_accessible_attributes
assert_default_attributes(best_friend, true) assert_default_attributes(best_friend, true)
end end
def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes
best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes
best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) best_friend = @person.create_best_friend!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
@ -406,12 +406,12 @@ def test_has_one_build_with_attr_accessible_attributes
assert_default_attributes(best_friend) assert_default_attributes(best_friend)
end end
def test_has_one_build_with_admin_scope_with_attr_protected_attributes def test_has_one_build_with_admin_role_with_attr_protected_attributes
best_friend = @person.best_friends.build(attributes_hash, :as => :admin) best_friend = @person.best_friends.build(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend) assert_admin_attributes(best_friend)
end end
def test_has_one_build_with_admin_scope_with_attr_accessible_attributes def test_has_one_build_with_admin_role_with_attr_accessible_attributes
best_friend = @person.best_friends.build(attributes_hash, :as => :admin) best_friend = @person.best_friends.build(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend) assert_admin_attributes(best_friend)
end end
@ -433,12 +433,12 @@ def test_has_one_create_with_attr_accessible_attributes
assert_default_attributes(best_friend, true) assert_default_attributes(best_friend, true)
end end
def test_has_one_create_with_admin_scope_with_attr_protected_attributes def test_has_one_create_with_admin_role_with_attr_protected_attributes
best_friend = @person.best_friends.create(attributes_hash, :as => :admin) best_friend = @person.best_friends.create(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
def test_has_one_create_with_admin_scope_with_attr_accessible_attributes def test_has_one_create_with_admin_role_with_attr_accessible_attributes
best_friend = @person.best_friends.create(attributes_hash, :as => :admin) best_friend = @person.best_friends.create(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
@ -460,12 +460,12 @@ def test_has_one_create_with_bang_with_attr_accessible_attributes
assert_default_attributes(best_friend, true) assert_default_attributes(best_friend, true)
end end
def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes
best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) best_friend = @person.best_friends.create!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end
def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes
best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) best_friend = @person.best_friends.create!(attributes_hash, :as => :admin)
assert_admin_attributes(best_friend, true) assert_admin_attributes(best_friend, true)
end end

@ -372,7 +372,7 @@ def signup
end end
</ruby> </ruby>
Mass-assignment saves you much work, because you don't have to set each value individually. Simply pass a hash to the new() method, or assign attributes=(attributes) a hash value, to set the model's attributes to the values in the hash. The problem is that it is often used in conjunction with the parameters (params) hash available in the controller, which may be manipulated by an attacker. He may do so by changing the URL like this: Mass-assignment saves you much work, because you don't have to set each value individually. Simply pass a hash to the +new+ method, or +assign_attributes=+ a hash value, to set the model's attributes to the values in the hash. The problem is that it is often used in conjunction with the parameters (params) hash available in the controller, which may be manipulated by an attacker. He may do so by changing the URL like this:
<pre> <pre>
"name":http://www.example.com/user/signup?user[name]=ow3ned&user[admin]=1 "name":http://www.example.com/user/signup?user[name]=ow3ned&user[admin]=1
@ -386,7 +386,7 @@ params[:user] # => {:name => “ow3ned”, :admin => true}
So if you create a new user using mass-assignment, it may be too easy to become an administrator. So if you create a new user using mass-assignment, it may be too easy to become an administrator.
Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example: Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3+. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example:
<ruby> <ruby>
class Person < ActiveRecord::Base class Person < ActiveRecord::Base
@ -410,7 +410,7 @@ To avoid this, Rails provides two class methods in your Active Record class to c
attr_protected :admin attr_protected :admin
</ruby> </ruby>
+attr_protected+ also optionally takes a scope option using :as which allows you to define multiple mass-assignment groupings. If no scope is defined then attributes will be added to the default group. +attr_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.
<ruby> <ruby>
attr_protected :last_login, :as => :admin attr_protected :last_login, :as => :admin
@ -433,7 +433,7 @@ params[:user] # => {:name => "ow3ned", :admin => true}
@user.admin # => true @user.admin # => true
</ruby> </ruby>
When assigning attributes in Active Record using +attributes=+, or +update_attributes+ the :default scope will be used. To assign attributes using different scopes you should use +assign_attributes+ which accepts an optional :as options parameter. If no :as option is provided then the :default scope will be used. You can also bypass mass-assignment security by using the +:without_protection+ option. Here is an example: When 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:
<ruby> <ruby>
@user = User.new @user = User.new
@ -451,7 +451,7 @@ When assigning attributes in Active Record using +attributes=+, or +update_attri
@user.is_admin # => true @user.is_admin # => true
</ruby> </ruby>
In a similar way, +new+, +create+ and <tt>create!</tt> methods respect mass-assignment security and accepts either +:as+ or +:without_protection+ options. For example: In a similar way, +new+, +create+, <tt>create!</tt>, +update_attributes+, and +update_attributes!+ methods all respect mass-assignment security and accept either +:as+ or +:without_protection+ options. For example:
<ruby> <ruby>
@user = User.new({ :name => 'Sebastian', :is_admin => true }, :as => :admin) @user = User.new({ :name => 'Sebastian', :is_admin => true }, :as => :admin)