When running my specs, I am stopped by a FactoryGirl
error before rspec can even iterate through them.
Finished in 0.18709 seconds (files took 1.57 seconds to load)
0 examples, 0 failures
/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/factory_girl-4.5.0/lib/factory_girl/linter.rb:14:in `lint!': The following factories are invalid: (FactoryGirl::InvalidFactoryError)
* program - Validation failed: Name has already been taken (ActiveRecord::RecordInvalid)
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/factory_girl-4.5.0/lib/factory_girl/linter.rb:4:in `lint!'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/factory_girl-4.5.0/lib/factory_girl.rb:59:in `lint'
from /spec/support/factory_girl.rb:9:in `block (2 levels) in <top (required)>'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/example.rb:333:in `instance_exec'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/example.rb:333:in `instance_exec'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/hooks.rb:357:in `run'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1559:in `block in run_hooks_with'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1559:in `each'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1559:in `run_hooks_with'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/configuration.rb:1525:in `with_suite_hooks'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:109:in `block in run_specs'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/reporter.rb:62:in `report'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:108:in `run_specs'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:86:in `run'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:70:in `run'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/lib/rspec/core/runner.rb:38:in `invoke'
from /.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.2.3/exe/rspec:4:in `<top (required)>'
from /.rbenv/versions/2.2.2/bin/rspec:23:in `load'
from /.rbenv/versions/2.2.2/bin/rspec:23:in `<main>'
Without the associated program
in the campaign
factory, my tests run fine with 15 examples, 2 failures
.
Here is my Factory..
FactoryGirl.define do
factory :campaign do |x|
x.sequence(:name) { |y| "Q6 201#{y}" }
x.sequence(:comment) { |y| "JIRA OI-6#{y}" }
channels ["Folder", "Fax"]
program
end
factory :program do
name "Caspian Star"
end
factory :plan do
name "Third Storm Connect"
end
end
My relevant models..
Class Campaign < ActiveRecord::Base
belongs_to :program
validates :program, presence: true
belongs_to :plan
end
Class Program < ActiveRecord::Base
has_many :campaigns
end
It definitely has to do with setting up the associated Program with Campaign but I can't figure out how to do it right. My intention is to not create multiple instances of program
but rather have the campaign associate with an existing one - or the one I create via FactoryGirl.
When using FactoryGirl's association :program
method, I get the same error. It doesn't seem to matter what I name the program
factory to either. I am also using DatabaseCleaner
to clear the test database after it runs.
I'm currently trying to test the validates :program, presence true
but keep running in circles with this.
Any help is highly appreciated.
UPDATE
Here are the specs as requested.
describe "Relationships" do
it { should belong_to :program }
...some unrelated relationship specs..
end
describe "Validations" do
it { should validate_presence_of :name }
it { should validate_uniqueness_of :name }
it { should serialize :channels }
it { should validate_presence_of :comment }
it { should validate_presence_of :program }
end
it "serializes column into Array" do
obj = build(:campaign)
obj.channels = [1,2,3]
obj.save!
expect(obj.reload.channels).to eq [1, 2, 3]
end
it 'validates associated campaign' do
campaign = build(:campaign)
expect(campaign.save).to be_valid?
expect(campaign.errors).to eq "You need to choose a Program."
end
end
UPDATE #2
After experimenting with some of the answers below, I can confirm that sequence
does not fix the error. However, when I completely remove the FactoryGirl association yet instantiate the association in the specs - I recieve the error Validation failed: Program can't be blank
. Note, my specs are still not running..
Finished in 0.19413 seconds (files took 1.54 seconds to load)
0 examples, 0 failures
Something is going on before it hits my specs and I believe the answer is what the error refers to lint!
I'm not too familiar with 'lint', as I set my Factory up following a blog. I checked the documentation and it appears that I have it set up correctly...however, it runs my Factories through my validations before the database is cleaned as well as before it runs any specs.
This is a problem when I want to validates :program, presence: true
and instantiate it in the spec. 'FactoryGirl.lint' interrupts my test letting me know it can't be blank
when that is exactly what I want the Factory to look like. So far, the only solution I can think of is to disable lint
as I was able get my specs to run with it disabled.. but now that I understand it more, I can see how it could become very useful.
Is there a win-win situation for this scenario? Can I still have lint
while preserving validations and associations the way I need them to be?
Here's a look at my spec/support/factory_girl.rb where lint
exists..
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.before(:suite) do
begin
DatabaseCleaner[:active_record].strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
DatabaseCleaner.start
FactoryGirl.lint
ensure
DatabaseCleaner.clean
end
end
end