Search code examples
ruby-on-railsrspecfactory-bot

Weird error when testing `has_many` association with a conditional scope with Rspec & FactoryBot


I am admittedly not great with Rsec & FactoryBot, so this could very well be due to my lack of experience, but I running into a weird issue when trying to test a has_many association with a where condition in which the unscoped association passes, but scoped association is empty but still has the correct count.

Here is the simplified setup:

  • Ruby 2.7
  • Rails 6.0
  • Rspec 3.12
  • FactoryBot 6.2

Models

class Club < ApplicationRecord
  has_many :members,
    inverse_of: :club,
    dependent: :nullify,
    autosave: true

  has_many :active_members,
    -> { where(active_status_id: [1, 2]) },
    inverse_of: :club,
    dependent: :nullify,
    autosave: true
end

class Member < ApplicationRecord
  belongs_to :active_status,
    inverse_of: :members

  belongs_to :club,
    inverse_of: :members,
    optional: true
end

Factories

FactoryBot.define do
  factory :club do

  end
end

FactoryBot.define do
  factory :member do

  end
end

Spec

RSpec.describe Club, type: :model do
  before do
    @club = create(:club)
  end

  describe 'clubs' do
    it 'a club is created' do
      expect(@club).to be_present # pass
    end
  end

  describe 'club members' do
    before do
      @member = create(:member, club: @club, active_status_id: 1)
    end

    context 'a new member' do
      expect(@member.approval_status_id).to eq(1) # pass
      expect(@member.club).to eq(@club) # pass

      expect(@club.members.count).to eq(1) # pass
      expect(@club.members.first).to eq(@member) # pass

      expect(@club.active_members.count).to eq(1) # pass
      expect(@club.active_members.first).to eq(@member) # fail ???

      # And when inspected, `@club.active_members` is: #<ActiveRecord::Associations::CollectionProxy []>
    end
  end
end

Why/how is the @club.active_members.count passing, but the @club.active_members.first fails?


Solution

  • Could you try reloading @club i.e @club.reload.active_members.first?

    By calling @club.reload, you refresh the association and ensure that the newly created @member is included in @club.active_members.