Search code examples
ruby-on-railsvalidationfactory-botnested-attributes

Factory Girl and nested attributes validation error


I have a model Company which accepts nested attributes for Recruiters model. I need to have validation in my Company model that at least one recruiter was created during Company creation.

class Company < ActiveRecord::Base
    has_many :recruiters, dependent: :destroy, inverse_of: :company
    accepts_nested_attributes_for :recruiters, reject_if: ->(attributes) { attributes[:name].blank? || attributes[:email].blank? }, allow_destroy: true

    validate { check_recruiters_number } # this validates recruiters number

    private

    def recruiters_count_valid?
       recruiters.reject(&:marked_for_destruction?).count >= RECRUITERS_COUNT_MIN
    end

    def check_recruiters_number
       unless recruiters_count_valid?
           errors.add(:base, :recruiters_too_short, count: RECRUITERS_COUNT_MIN)
       end
    end
end

Validation works as expected but after adding this validation I have a problem with FactoryGirl. My factory for company looks like this:

FactoryGirl.define do
   factory :company do
        association :industry
        association :user
        available_disclosures 15
        city 'Berlin'
        country 'Germany'

        ignore do
            recruiters_count 2
        end

        after(:build) do |company, evaluator|
            FactoryGirl.create_list(:recruiter, evaluator.recruiters_count, company: company)
        end

        before(:create) do |company, evaluator|
            FactoryGirl.create_list(:recruiter, evaluator.recruiters_count, company: company)
        end
    end 
end  

In tests, when I do

company = create(:company)

I get validation error:

ActiveRecord::RecordInvalid:
   Validation failed: Company has to have at least one recruiter

When I first build company and then save it, the test passes:

company = build(:company)
company = save

Of course, I don't want to change all my tests this way to make them work. How can I set up my factory to create associated model during creation Company model?


Solution

  • Your validate { check_recruiters_number } is unreasonable. Remove it.

    Why? You need to have a valid company id to save recruiters, but your validator prevent company to be valid because it has no recruiters. This is in contradiction.