Factory Girl has_many through validation deadlock

2019-08-07 13:56发布

问题:

I have a Listing model which has_many :categories, through: :categories_listings and has_many :categories_listings. I was testing it with a Factory Girl factory which looks like this:

factory :listing do |f|
  f.sequence (:title) { |n| "Listing #{n}" }
  message {Faker::Lorem.paragraph}
  cards {[FactoryGirl.create(:card)]}
  categories {[FactoryGirl.create(:category)]}
  association :delivery_condition
  association :unit_of_measure
  quantity 1
  unit_price 1
end

And everything was OK until I added the following validation to the model:

validate :has_categories?

def has_categories?
  if self.categories_listings.blank?
    errors.add :base, "You have to add at least one category"
  end
end

Now whenever I run the factory I get:

ActiveRecord::RecordInvalid: You have to add at least one category

I also tried with Factory Girl callbacks like before :create but the problem is that I can't add the association because I don't yet know the listing id in the callback. But I can't save the listing because validations are run before the association.

How can I get around this and make it work?

回答1:

Made it work.

In my factory I removed the categories line and added a before(:create) callback which BUILDS the relationship. Emphasis on builds as it wouldn't work with create (I tried that before posting the question). Plus build bypasses the deadlock I was mentioning. So now, the working factory looks like this:

factory :listing do |f|
  f.sequence (:title) { |n| "Listing #{n}" }
  message { Faker::Lorem.paragraph }
  cards { [FactoryGirl.create(:card)] }
  association :delivery_condition
  association :unit_of_measure
  quantity 1
  unit_price 1

  before(:create) do |listing|
    category = FactoryGirl.create(:category)
    listing.categories_listings << FactoryGirl.build(:categories_listing, listing: listing, category: category)
  end
end

Got my inspiration from this answer.