Search code examples
ruby-on-railsrubyarraysrspecmodel-associations

When using the 'build' command in rails, before a save, my array of zombie.weapons has 2 weapons in it, but zombie.weapons.count = 0


In RSpec Testing for Zombies, I'm trying to get this test to pass

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

To do this, I've utilized a after_initialize model callback to create ('build') the weapons

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

Right now the tests aren't passing, but there's one more issue, namely the one in the title. So in the rails console…

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>] 

That looks like we're getting what we want as described in the test, but when I do this:

z.weapons.count
#=> 0

Hence the failing test. How does this array with 2 entities have a count of 0? This is a rails question surrounding 'build' etc, but its also a ruby question. That array has two entities in it but ruby is seemingly 'lying' about it


Solution

  • That's the way count works, it performs an SQL count in the database, but your records are not saved yet, so it gives zero.

    z.weapons.size or z.weapons.length will give you what you expect.

    Check this out for example: http://rhnh.net/2007/09/26/counting-activerecord-associations-count-size-or-length