2

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

coloradoblue
  • 625
  • 7
  • 11

2 Answers2

2

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

deivid
  • 4,808
  • 2
  • 33
  • 38
0

According to this post, there's some documentation stating that after_initialize is ignored if defined as you've done.

However, it seems that the poster observed behavior that conflicts with that documentation, so YMMV. (It may depend on the version of Rails you're using, but this is speculation.)

I wish I could give a more definitive answer, but hopefully this can be a springboard for someone more familiar with the behavior of after_initialize.

Community
  • 1
  • 1
bschnur
  • 342
  • 3
  • 9