При использовании команды build в рельсах перед сохранением в моем массиве zombie.weapons есть 2 оружия, но zombie.weapons.count = 0

В RSpec Testing for Zombies я пытаюсь пройти этот тест

describe Zombie do
  it "starts off with two weapons" do
    z = Zombie.new(:name => "Ash")
    z.weapons.count.should == 2
  end
end

Для этого я использовал обратный вызов модели after_initialize для создания ('сборки') оружия.

class Zombie < ActiveRecord::Base
  after_initialize :grant_two_weapons

  def grant_two_weapons
     self.weapons.build(:name => "axe")
     self.weapons.build(:name => "stick")
  end
end

Сейчас тесты не проходят, но есть еще одна проблема, а именно та, что указана в заголовке. Итак, в консоли рельсов…

z = Zombie.new
z.weapons
#=> [#<Weapon id: nil, name: "axe", zombie_id: nil, created_at: nil, updated_at: nil>, #<Weapon id: nil, name: "stick", zombie_id: nil, created_at: nil, updated_at: nil>] 

Похоже, мы получаем то, что хотим, как описано в тесте, но когда я делаю это:

z.weapons.count
#=> 0

Отсюда неудачный тест. Каким образом этот массив с двумя объектами имеет счетчик 0? Это вопрос рельсов, связанный с «сборкой» и т. Д., Но это также вопрос рубина. В этом массиве есть две сущности, но рубин, похоже, `` лжет '' об этом


person coloradoblue    schedule 02.03.2013    source источник
comment
Мне удалось пройти тест, вызвав self.save в методе grant_two_weapons, но теоретические вопросы все еще остаются   -  person coloradoblue    schedule 02.03.2013
comment
плюс мне кажется, что я как-то обманул, чтобы пройти тест   -  person coloradoblue    schedule 02.03.2013


Ответы (2)


Так работает count, он выполняет подсчет SQL в базе данных, но ваши записи еще не сохранены, поэтому он дает ноль.

z.weapons.size или z.weapons.length даст вам то, что вы ожидаете.

Посмотрите это, например: http://rhnh.net/2007/09/26/counting-activerecord-associations-count-size-or-length

person deivid    schedule 02.03.2013

Согласно этому сообщению, есть документация, в которой указано, что after_initialize игнорируется, если определено, как вы сделали.

Однако похоже, что на плакате наблюдалось поведение, которое противоречит этой документации, поэтому YMMV. (Это может зависеть от версии Rails, которую вы используете, но это предположение.)

Хотел бы я дать более определенный ответ, но, надеюсь, это может стать трамплином для кого-то, кто более знаком с поведением after_initialize.

person bschnur    schedule 02.03.2013