Search code examples
ruby-on-railsfactory-botrspec-rails

Rails / Rspec - writing spec involving custom validation and belongs_to associations


I have the following AR has_many, belongs_to relationships:

League --> Conference --> Division --> Team

I have an Event model that looks like this:

class Event < ActiveRecord::Base
  belongs_to :league
  belongs_to :home_team, :class_name => 'Team', :foreign_key => :home_team_id
  belongs_to :away_team, :class_name => 'Team', :foreign_key => :away_team_id

  validate :same_league

  def same_league
    return if home_team.blank? || away_team.blank?
    errors.add :base, "teams must be in the same league" if home_team.league != away_team.league
  end
end

And some factories:

FactoryGirl.define do
  factory :league do
    name 'NFL'
  end
end

Factory.define :conference do |f|
  f.name 'NFC'
  f.association :league
end

Factory.define :division do |f|
  f.name 'North'
  f.association :conference
end

Factory.define :team do |f|
  f.name 'Packers'
  f.locale 'Green Bay'
  f.association :division
end

FactoryGirl.define do
  factory :event do
    association :league
    association :home_team, :factory => :team
    association :away_team, :factory => :team
  end
end

So with all that, how would I go about writing a spec for the same_league validation method?

describe Event do
  pending 'should not allow home_team and away_team to be from two different leagues'
end

My issue is knowing what the simplest way to go about creating two teams in different leagues and associating one with home_team and the other with away_team in the event model.


Solution

  • You can store instances you generate with factories and then explicitly use their ID's to fill in the foreign keys for subsequent factories.

    Here I'm creating two leagues, then setting up two tests. One where the event has two teams in the same league and another with two teams in different leagues. This way I can test if the event object is properly validating:

    describe Event do
      before(:each) do
        @first_league = Factory(:league)
        @second_league = Factory(:league)
      end
      it "should allow the home_team and away_team to be from the same league" do
        home_team = Factory(:team, :league_id => @first_league.id)
        away_team = Factory(:team, :league_id => @first_league.id)
        event = Factory(:event, :home_team_id => home_team.id, :away_team_id => away_team.id)
        event.valid?.should == true
      end
      it "should not allow the home_team and away_team to be from two different leagues" do
        home_team = Factory(:team, :league_id => @first_league.id)
        away_team = Factory(:team, :league_id => @second_league.id)
        event = Factory(:event, :home_team_id => home_team.id, :away_team_id => away_team.id)
        event.valid?.should == false
      end
    end