jeudi 14 avril 2016

Factory Girl self-join throwing validation errors

I'm trying to test a system for creating article translations where there is a self-join on the publications table. I've created a factory that will create multiple translations and associate them with a 'parent' article.

Using Rails 5 with factory_girl 4.7.0, rspec, and Database_cleaner

All actions work as expected, but creating a test is the problem

Here's the relevant model validations and methods:

  # models/publication.rb

  has_many :translations, class_name: "Publication", foreign_key: "translation_id", dependent: :nullify
  belongs_to :translation, class_name: "Publication", optional: true

  validates :language, uniqueness: { scope: :translation_id }, if: :is_translation?

  def is_translation?
    !translation.nil?
  end

Factory (irrelevant code omitted):

  # spec/factories/publication.rb
  factory :publication, aliases: [:published_pub] do
    title 'Default Title'
    language 'EN'
    published

    after(:build) do |object|
      create(:version, publication: object)
    end

    #-- This is where I suspect the problem stems from

    trait :with_translations do
      association :user, factory: :random_user

      after(:build) do |object|
        create_list(:translation, 3, {user: object.user, translation:object})
      end
    end
  end

  factory :translation, class: Publication do
    sequence(:title) { |n| ['French Article', 'Spanish Article', 'German Article', 'Chinese Article'][n]}
    sequence(:language) { |n| ['FR', 'ES', 'DE', 'CN'][n]}
    user
  end

And a basic test:

    # spec/models/publication_spec.rb
    before(:each) do
      @translation_parent = create(:publication, :with_translations)
      @pub_without_trans = create(:publication, :with_random_user)
    end

    scenario 'is_translation?' do
      # No actual test code needed, this passes regardless
    end

    scenario 'has_translations?' do
      # No actual test code needed, this (and subsequent tests) fail regardless
    end

Finally, the error:

 Failure/Error: create_list(:translation, 3, {user: object.user, translation:object})

 ActiveRecord::RecordInvalid:
   Validation failed: Language has already been taken

The first test passes (and the publication object with translations is created correctly)but any subsequent test fails. The issue is that I have a uniqueness validation scoped to translation_id and it appears that factorygirl is trying to add the generated translations to an already existing publication instead of creating an entirely new publication.

Any help is appreciated!

Aucun commentaire:

Enregistrer un commentaire