Rails тестирование ассоциации has_many - PullRequest
0 голосов
/ 25 сентября 2011

У меня 2 модели. A 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

Я добавил тестовый пример для отношения assign_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

Теперь этот тестовый пример не пройден. Это не соответствует последнему утверждению. Если я уберу предыдущее утверждение (помеченное «СМОТРИТЕ НА МЕНЯ»), этот тест пройдет нормально. Это также проходит нормально, если я изменю эту строку на 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 с ванильным приложением

1 Ответ

2 голосов
/ 25 сентября 2011

Вам необходимо перезагрузить 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 служит для улучшения поведения в памяти и может также решить вашу проблему (без перезагрузки),Читайте об этом здесь .Это выглядело бы примерно так (но опять же я не уверен, что в этом случае это будет работать):

# 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)
...