Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Mass Assignment Error

Running the following test in the "What is a join table" lesson

test "should create status for the current user when logged in" do
    sign_in users(:jason)

    assert_difference('Status.count') do
      post :create, status: {content: @status_content, user_id: users(:jim).id}
    end

    assert_redirected_to status_path(assigns(:status))
    assert_equal assigns(:status).user_id, users(:jason).id
  end

I get the following error:

  2) Error: 
test_should_create_status_when_logged_in(StatusesControllerTest): 
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes:    id, created_at, updated_at

I believe the issue is with the attr_accessible definition in the user model. I've added both :status and :id but the error still persists.

Any one have a idea?

4 Answers

In case anyone is following this....

As detailed above adding the :created_at and :updated_at attributes to the status model resolves the MassAssignmentSecurity::Error.

However, this is not the best solution. I believe by adding these attributes unnecessarily you could introduce security issues (which is why RoR prevents you from mass assigning in the first place).

The MassAssignmenetSecurity::Error is caused by the following line of code

post :create, status: @status.attributes

From what I understand (please correct me if I'm wrong), by assigning the @status.attributes to the status: variable, you are in effect mass assigning all its attributes.

One solution is to allow access to all the attributes. The other is to assign only the accessible attributes individually. This is accomplished with the following code.

post :create, status: {content: @status.content, user_id: users(:jason).id}

This fixes the error because you are no longer mass assign and it doesn't require adding the :created_at and :updated_at attributes to the status model.

First of all, thank you for posting such a great resonse. Its the only place I could find a fix a solution with explanation. I just want to add a couple lines of code so people can see where the corrections were made (not everones line 37 is the same).

  test "should update status" do
    put :update, id: @status, status: @status.attributes
    assert_redirected_to status_path(assigns(:status))
  end

Should be changed to:

  test "should update status" do
    post :create, status: {content: @status.content, user_id: users(:jason).id}
    assert_redirected_to status_path(assigns(:status))
  end
Rob Allessi
Rob Allessi
8,600 Points

Hi Matthew,

Thanks for reaching out to us! We alerted one of our teachers to look into this and provide you with some assistance and they should get back to you soon on this!

Joins usually involve two models that are "joining" two sets of data together. You are right that the mass assignment protection feature in Rails 3 has to do with the attr_accessible definition. Try adding the foreign key under the attr_accessible line.

The error is caused by line 37 in my statuses_controller_test.rb

post :create, status: @status.attributes

Which leads to this error

2) Error: 
test_should_create_status_when_logged_in(StatusesControllerTest): 
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes:       id, created_at, updated_at

When I add the missing attributes to my status.rb model

attr_accessible :content, :user_id, :created_at, :updated_at 

Error resolved.