ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes
Asked Answered
S

7

26

If I try to execute the following code:

hassle = rota.hassles.create(:sender => user1, :receiver => user2, :type => "sms")

I obain the following error:

Failure/Error: hassle = rota.hassles.create(:sender => user1, :receiver => user2, :type => "sms")
 ActiveModel::MassAssignmentSecurity::Error:
   Can't mass-assign protected attributes: type

I am not sure what this means. I have made the :type to be compulsory, so if I do remove it, I get an sql error.

Solorzano answered 13/5, 2012 at 20:25 Comment(3)
The "type" column is used by default by rails for STI. Best solution is to rename the type column to something else. A not recommended workaround is to add on your model file self.inheritance_column = :some_other_column_that_might_not_existsObelize
Yes -- see this for info on getting around the STI issue of using the 'type' column : #7135059 (though a better option may be to change the name of the column).Wardship
yeah - I ran into this issue. Changed column name. thnks!Solorzano
W
67

A couple things:

Mass Assignment usually means passing attributes into the call that creates an object as part of an attributes hash. That is, you pass a bunch of attributes in a hash into the call that creates the new object. For example:

@user = User.create({:name => "My name", :user_type => "nice_user"})

However, Rails includes some basic security rules that mean not all attributes can be assigned that way by default. You have to specify which ones can beforehand. You do so like this:

class User < ActiveRecord::Base
  attr_accessible :name, :user_type
end

If you don't specify an attribute is attr_accessible, and you pass it in to create the object, you get the error you posted.

Here are more details:

http://api.rubyonrails.org/v3.2.9/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html

The alternative is to set some of the attributes when you first create the record, and set others after -- like so:

# In this example `user_type` is not attr_accessible so it needs to be set specifically
@user = User.create({:name => "My name"})
@user.user_type = "nice_user"
@user.save

In addition, if you're having issues with using the column name type because rails is getting confused and thinks you want to use Single Table Inheritance (STI), check the answer to this question to see how to get around it: http://guides.rubyonrails.org/

Wardship answered 13/5, 2012 at 20:38 Comment(1)
what if you try to create a parent with many child at once? e.g; Post.create(comments)Kendyl
V
8

Are you working with Rails 3.2 while following a 3.1 tutorial such as the Pragmatic Programmer's "Agile Web Development with Rails" 4th edition? Then check http://guides.rubyonrails.org/3_2_release_notes.html.

Your problem is that from Rails 3.1 to 3.2 checking of mass assignment protection for Active Record models is set to 'strict' by default. Comment out the appropriate lines in these files:

config/environments/development.rb
config/environments/test.rb

... and you're good to go on learning. Remember to leave this in effect when coding your first production application :)

Vonvona answered 19/7, 2012 at 16:43 Comment(2)
"Are you working with Rails 3.2 while following a 3.1 tutorial such as the Pragmatic Programmer's "Agile Web Development with Rails" 4th edition?" That's exactly what I'm doing. +1 for fixing my problem.Aholla
This fixed my problem, i commented out this line: config.active_record.mass_assignment_sanitizer = :strictUndersized
C
5
  1. Please try: open config/application.rb

  2. Locate the line of config.active_record.whitelist_attributes = true

  3. Change true to false

Then you shall be fine.

PS: remember to restart the rails console.

Classmate answered 11/12, 2013 at 3:31 Comment(0)
C
2

You should be getting another error, like this: column 'type' is reserved for storing the class in case of inheritance. Because Column 'type' should not be used in active record database.

Camilla answered 11/12, 2013 at 3:58 Comment(0)
E
1

I do not use whitelist_attributes since use cases when I do want to allow mass-assignment are for my internal logic and usually not directly in Controller for CRUD actions. I suggest using strong params in those cases. But when you want to enable mass-assignment for specific model you do

class Foo < ActiveRecord::Base
  # disables mass-assigment
  attr_protected
end

This basically sets attr_protected to empty array ([])

Exalted answered 5/6, 2014 at 7:30 Comment(0)
M
0

Here is some info on what mass assignment in Rails is, and why the protection is in place. It's pretty easy to get around when you really do want to assign a protected attribute, but it takes a couple of extra lines.

hassle = rota.hassles.build(:sender => user1, :receiver => user2)
hassle.type = 'sms'
hassle.save
Mews answered 13/5, 2012 at 20:31 Comment(2)
hassle.type = 'sms' most probably will raise an Sms class doesn't exists exceptionObelize
Perhaps. I'm working under the assumption that OP knows what he's doing wrt STI.Mews
D
0

You need to having attr_accesible in your model class

class <model_name> < ActiveRecord::Base
    attr_accessible :<fields_name>
end
Dachau answered 24/8, 2021 at 6:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.