In a project I am currently working on, I have a one-way relationship using a belongs_to association. I wanted to use the newer Nested Object Forms functionality added in Rails 2.3 to allow me to modify the properties of the related object in one form.
For the purposes of this post I’m going to use the following simplified code:
#address.rb class Address < ActiveRecord::Base attr_accesible :address_string end #user.rb class User < ActiveRecord::Base attr_accessible :name belongs_to :address accepts_nested_attributes_for :address end
I ran into an issue when I was testing out this functionality in script/console and trying to assign attributes to the address through the user. I would encounter the error “WARNING: Can’t mass-assign these protected attributes: address_attributes” in my development.log. I proceeded to try and google a solution to this problem, and found many posts from users which encountered this issue, but none of them provided a solution. It appeared many people simply abandoned attempting to use nested attributes with a :belongs_to association. The solution to this problem is actually quite simple (once you know it!). Here’s the console log and the database log from my initial attempt:
#script/console >> user = User.first=> #<User id: 1, name: "Bill", address_id: 1, created_at: "2010-08-20 21:49:52", updated_at: "2010-08-20 22:06:37"> >> params = {:address_attributes => {:address_string => "Up the tree", :id => 1}} => {:address_attributes=>{:address_string=>"Up the tree", :id=>1}} >> user.update_attributes(params)=> true >> user.address=> #<Address id: 1, address_string: "down the street", created_at: "2010-08-20 21:49:53", updated_at: "2010-08-20 21:49:53"> #development.log WARNING: Can't mass-assign these protected attributes: address_attributes
Note that the console even returns true from the operation, but the update address attributes aren’t assigned and the string is still “down the street” instead of “Up the tree” that we were trying to assign. The solution to this problem is to make sure that address attributes are added to the attr_accesible in the user model:
#user.rb class User < ActiveRecord::Base attr_accessible :name, :address_attributes belongs_to :address accepts_nested_attributes_for :address end
Now the error will no longer occur, and the address will be succesfully updated, as in the following console log.
#script/console >> user = User.first=> #<User id: 1, name: "Bill", address_id: 1, created_at: "2010-08-20 21:49:52", updated_at: "2010-08-20 22:06:37"> >> params = {:address_attributes => {:address_string => "Up the tree", :id => 1}} => {:address_attributes=>{:address_string=>"Up the tree", :id=>1}} >> user.update_attributes(params) => true >> user.address=> #<Address id: 1, address_string: "Up the tree", created_at: "2010-08-20 21:49:53", updated_at: "2010-08-20 22:41:46">
I hope this post can help save some time for others who run across this same issue.
Happy Coding!