In rails 3.0.9/ruby 1.9.2 I’m getting unexpected behaviour when i try to update model foreign keys.
I start with a fresh install
$ rails new mytest
$ rails g model User
$ rails g model Ad user_id:integer
$ rake db_migrate
Add association in app/models/Ad.rb
Class User < ActiveRecord::Base
belongs_to :user
end
Now to the fun part. I want to change the foreign key on an object directly. I enter rails console with rails c
$ u = User.create
$ a=Ad.create(:user=>u)
$ a.update_attributes(:user_id => 9999)
$ a.user_id
=> 4
So that doesn’t work. I try to set the object directly instead of passing it to create:
$ u = User.create
$ a=Ad.create
$ a.user = u
$ a.save
$ a.update_attributes(:user_id => 9999)
$ a.user_id
=> 5
Doesn’t work.
The only thing that works is this:
$ u = User.create
$ a=Ad.create
$ a.user_id = u.id
$ a.save
$ a.update_attributes(:user_id => 9999)
$ a.user_id
=> 9999
Can someone please explain what is going on, and how can I change the foreign keys of my objects? I assume the “blocking” behaviour happens when the objects associations are instantiated and there is a conflict, so one answer is to do this:
$ Ad.find( a.id ).update_attributes( :user_id => xxxx )
That works. But it seems like a long way to go just for changing a foreign key on an object. It also takes an extra DB hit, and lastly it is quite messy code if an object internally needs to update itself. What to do?
Just unload the loaded object before doing the update
You can make Factory girl create objects with unloaded associations like this