我有2个型号。一个User
和一个Task
。以下是他们的代码:
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
架构非常明显,但为了保持一致性,它的外观如下:
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
我为assigned_tasks关系添加了一个测试用例。它看起来像这样:
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
现在,这个测试用例失败了。它在最后一个断言中失败了。如果我删除了之前的断言(标记为“LOOK AT ME”),则该测试通过正常。如果我将此行更改为assert u2.assigned_tasks
,它也会正常传递。这意味着只有当empty?
被u2.assigned_tasks
调用时,它才会出现中断。在断言通过的地方,下面的一个失败了。这是失败:
UserTest:
FAIL assigned tasks (0.12s)
<1> expected but was
<0>.
test/unit/user_test.rb:12:in `block in <class:UserTest>'
因此,在原始empty?
数组上调用u2.assigned_tasks
后,该任务实际上并未与其指定的用户相关/关联。然而,这似乎在控制台中工作正常。
道歉,如果我完全忽略了这里简单的事情,但我真的无法理解这一点。正确方向的任何一点都会非常有帮助。感谢
PS:Rails 3.1 with vanilla application
答案 0 :(得分:2)
您需要重新加载assigned_tasks
或u2
。
# This line causes assigned_tasks to be loaded and cached on u2. Not the calling
# of empty?, but rather the loading of the association.
assert_empty u2.assigned_tasks
# but then you actually make the task here
task = u1.tasks.create(:name => 'some task', :assigned_user_id => u2.id)
# so when this assertion happens, u2 already has an empty set of tasks cached,
# and fails
assert_equal 1, u2.assigned_tasks.size
# however either of these should pass
assert_equal 1, u2.assigned_tasks(true).size
assert_equal 1, u2.reload.assigned_tasks.size
inverse_of
选项用于改善内存中的关联行为,也可能解决您的问题(无需重新加载)。阅读here。它看起来像这样(但是我不肯定它会在这种情况下起作用):
# on User
has_many :assigned_tasks, ..., :inverse_of => :assigned_user
# on Task
belongs_to :assigned_user, ..., :inverse_of => :assigned_tasks
# in your test you might have to change the task creation to:
u1.tasks.create(:name => 'some task', :assigned_user => u2)