web-dev-qa-db-fra.com

Factory Girl: Comment configurer une association has_many /

J'ai eu du mal à mettre en place une relation has_many/through à l'aide de Factory Girl.

J'ai les modèles suivants:

class Job < ActiveRecord::Base
  has_many :job_details, :dependent => :destroy
  has_many :details, :through => :job_details
end

class Detail < ActiveRecord::Base
  has_many :job_details, :dependent => :destroy
  has_many :jobs, :through => :job_details
end

class JobDetail < ActiveRecord::Base
  attr_accessible :job_id, :detail_id
  belongs_to :job
  belongs_to :detail
end

Mon usine:

factory :job do
  association     :tenant
  title           { Faker::Company.catch_phrase }
  company         { Faker::Company.name }
  company_url     { Faker::Internet.domain_name }
  purchaser_email { Faker::Internet.email }
  description     { Faker::Lorem.paragraphs(3) }
  how_to_apply    { Faker::Lorem.sentence }
  location        "New York, NY"
end

factory :detail do
  association :detail_type <--another Factory not show here
  description "Full Time"
end

factory :job_detail do
  association :job
  association :detail
end

Ce que je veux, c'est que ma fabrique de jobs soit créée avec une valeur par défaut Detail de "Temps plein".

J'ai essayé de suivre cela, mais je n'ai pas eu de chance: FactoryGirl Has Many through

Je ne suis pas sûr de la manière dont le after_create devrait être utilisé pour attacher le détail via JobDetail.

29
cman77

Essayez quelque chose comme ça. Vous souhaitez créer un objet detail et l'ajouter à l'association de détail du travail. Lorsque vous utilisez after_create, le travail créé sera renvoyé au bloc. Vous pouvez donc utiliser FactoryGirl pour créer un objet de détail et l'ajouter directement aux détails de ce travail.

factory :job do
  ...

  after_create do |job|
    job.details << FactoryGirl.create(:detail)
  end
end
32
Logan Serman

J'ai fait face à ce problème aujourd'hui et j'ai trouvé une solution. J'espère que ça aide quelqu'un.

FactoryGirl.define do
  factory :job do

    transient do
      details_count 5 # if details count is not given while creating job, 5 is taken as default count
    end

    factory :job_with_details do
      after(:create) do |job, evaluator|
        (0...evaluator.details_count).each do |i|
          job.details << FactoryGirl.create(:detail)
        end
      end
    end
  end  
end

Cela permet de créer un travail comme celui-ci

create(:job_with_details) #job created with 5 detail objects
create(:job_with_details, details_count: 3) # job created with 3 detail objects
4
Sasi_Kala

Cela a fonctionné pour moi

FactoryGirl.define do
  factory :job do

    # ... Do whatever with the job attributes here

    factory :job_with_detail do

      # In later (as of this writing, unreleased) versions of FactoryGirl
      # you will need to use `transitive` instead of `ignore` here
      ignore do
        detail { create :detail }
      end

      after :create do |job, evaluator|
        job.details << evaluator.detail
        job.save
        job_detail = job.job_details.where(detail:evaluator.detail).first

        # ... do anything with the JobDetail here

        job_detail.save
      end
    end
  end
end

Puis plus tard

# A Detail object is created automatically and associated with the new Job.
FactoryGirl.create :job_with_detail

# To supply a detail object to be associated with the new Job.
FactoryGirl.create :job_with_detail detail:@detail
2
Nate

Vous pouvez résoudre ce problème de la manière suivante:

FactoryBot.define do
  factory :job do
    # job attributes

    factory :job_with_details do
      transient do
        details_count 10 # default number
      end

      after(:create) do |job, evaluator|
        create_list(:details, evaluator.details_count, job: job)
      end
    end
  end
end

Avec cela, vous pouvez créer un job_with_details, qui a des options pour spécifier le nombre de détails que vous voulez. Vous pouvez lire cet article intéressant pour plus de détails.

0
Nesha Zoric