I have 2 models. A User and a Task. Here’s the code for them both:
class User < ActiveRecord::Base
has_many :tasks
has_many :assigned_tasks, :class_name => 'Task', :foreign_key => 'assigned_user_id'
end
class Task < ActiveRecord::Base
belongs_to :user
belongs_to :assigned_user, :class_name => 'User', :foreign_key => 'assigned_user_id'
end
The schema is quite obvious, but for consistency, this is how it looks:
ActiveRecord::Schema.define(:version => 20110925050945) do
create_table "tasks", :force => true do |t|
t.string "name"
t.integer "user_id"
t.integer "assigned_user_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
end
I’ve added a test case for the assigned_tasks relationship. It looks like this:
class UserTest < ActiveSupport::TestCase
test "assigned tasks" do
u1 = User.create(:name => 'john')
u2 = User.create(:name => 'dave')
assert_empty u2.assigned_tasks # LOOK AT ME
task = u1.tasks.create(:name => 'some task', :assigned_user_id => u2.id)
assert_equal 1, u2.assigned_tasks.size
end
end
Now, this test case fails. It fails on the last assertion. If I remove the previous assertion (marked ‘LOOK AT ME’), this test passes fine. It also passes fine if I change this line to assert u2.assigned_tasks. Meaning it appears to break when, and only when, empty? is called against u2.assigned_tasks. Where that assertion passes, the following one fails. Here’s the failure:
UserTest:
FAIL assigned tasks (0.12s)
<1> expected but was
<0>.
test/unit/user_test.rb:12:in `block in <class:UserTest>'
So, it appears once empty? is called on the original u2.assigned_tasks Array, the task is not actually added/associated with it’s assigned user. This however appears to work fine in console.
Apologies if I’m completely overlooking something simple here, but I really can’t make any sense of this. Any points in the right direction would be extremely helpful. Thanks
PS: Rails 3.1 with a vanilla application
You need to reload the
assigned_tasks, oru2.The
inverse_ofoption serves to improve in-memory association behavior, and might also solve your problem (without reloading). Read about that here. It would look something like this (but again I’m not positive it will work in this case):