Come creare associazioni has_and_belongs_to_many in Factory Girl
-
18-09-2019 - |
Domanda
Dato il seguente
class User < ActiveRecord::Base
has_and_belongs_to_many :companies
end
class Company < ActiveRecord::Base
has_and_belongs_to_many :users
end
Come si fa a definire le fabbriche per le aziende e gli utenti, tra cui l'associazione bidirezionale? Ecco il mio tentativo
Factory.define :company do |f|
f.users{ |users| [users.association :company]}
end
Factory.define :user do |f|
f.companies{ |companies| [companies.association :user]}
end
Ora provo
Factory :user
Forse non sorprende questo si traduce in un ciclo infinito come fabbriche ricorsivamente usano tra loro per definire se stessi.
Più sorprendentemente non ho trovato una menzione di come fare questo da nessuna parte, c'è un modello per definire le fabbriche necessarie o sto facendo qualcosa di fondamentalmente sbagliato?
Soluzione 2
factorygirl da allora è stato aggiornato e ora include callback per risolvere questo problema. Date un'occhiata a http://robots.thoughtbot.com/post / 254496652 / aint-no-calla-back-girl per maggiori informazioni.
Altri suggerimenti
Ecco la soluzione che funziona per me.
FactoryGirl.define do
factory :company do
#company attributes
end
factory :user do
companies {[FactoryGirl.create(:company)]}
#user attributes
end
end
se avrete bisogno di società specifica è possibile utilizzare fabbrica in questo modo
company = FactoryGirl.create(:company, #{company attributes})
user = FactoryGirl.create(:user, :companies => [company])
Spero che questo sarà utile per qualcuno.
A mio parere, Basta creare due stabilimenti diversi, come:
Factory.define :user, :class => User do |u| # Just normal attributes initialization end Factory.define :company, :class => Company do |u| # Just normal attributes initialization end
Quando si scrivono i test-casi per gli utilizzatori poi basta scrivere come questo
Factory(:user, :companies => [Factory(:company)])
Spero che funzionerà.
non ho potuto trovare un esempio per il caso sopra menzionato sul sito web fornito. (Solo 1: N e association polimorfici, ma non HABTM). Ho avuto un caso simile e il mio codice simile al seguente:
Factory.define :user do |user|
user.name "Foo Bar"
user.after_create { |u| Factory(:company, :users => [u]) }
end
Factory.define :company do |c|
c.name "Acme"
end
Quello che ha funzionato per me è stato la creazione dell'associazione quando si utilizza la fabbrica. Usando il tuo esempio:
user = Factory(:user)
company = Factory(:company)
company.users << user
company.save!
factory :company_with_users, parent: :company do
ignore do
users_count 20
end
after_create do |company, evaluator|
FactoryGirl.create_list(:user, evaluator.users_count, users: [user])
end
end
Attenzione: gli utenti cambiano: [utente] per: gli utenti => [utente] per Ruby 1.8.x
Trovato questo modo piacevole e verbose:
FactoryGirl.define do
factory :foo do
name "Foo"
end
factory :bar do
name "Bar"
foos { |a| [a.association(:foo)] }
end
end
Prima di tutto vi incoraggio vivamente di utilizzare has_many: attraverso invece di HABTM (più su questo qui ), quindi vi ritroverete con qualcosa di simile:
Employment belongs_to :users
Employment belongs_to :companies
User has_many :employments
User has_many :companies, :through => :employments
Company has_many :employments
Company has_many :users, :through => :employments
Dopo questo avrete associazione has_many su entrambi i lati e possono assegnare loro in factory_girl nel modo avete fatto.
Aggiornamento per Rails 5:
Invece di usare associazione has_and_belongs_to_many
, si dovrebbe prendere in considerazione:. Associazione has_many :through
La fabbrica utente per questa associazione si presenta così:
FactoryBot.define do
factory :user do
# user attributes
factory :user_with_companies do
transient do
companies_count 10 # default number
end
after(:create) do |user, evaluator|
create_list(:companies, evaluator.companies_count, user: user)
end
end
end
end
È possibile creare la fabbrica società in un modo simile.
Una volta che entrambi gli stabilimenti sono impostati, è possibile creare fabbrica user_with_companies
con companies_count option
. Qui è possibile specificare il numero di società cui appartiene l'utente: create(:user_with_companies, companies_count: 15)
Si possono trovare spiegazioni dettagliate su associazioni Factory Girl qui .
È possibile definire nuovo stabilimento e l'uso dopo (: creare) callback per creare un elenco di associazioni. Vediamo come farlo in questo esempio:
FactoryBot.define do
# user factory without associated companies
factory :user do
# user attributes
factory :user_with_companies do
transient do
companies_count 10
end
after(:create) do |user, evaluator|
create_list(:companies, evaluator.companies_count, user: user)
end
end
end
end
Attributo companies_count è un transitorio e disponibile in attributi della fabbrica e nella richiamata tramite il valutatore. Ora, è possibile creare un utente con le aziende con la possibilità di specificare il numero di aziende che si desidera:
create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 15
Per HABTM ho usato tratti e callback .
Diciamo che sono i seguenti modelli:
class Catalog < ApplicationRecord
has_and_belongs_to_many :courses
…
end
class Course < ApplicationRecord
…
end
È possibile definire la fabbrica sopra :
FactoryBot.define do
factory :catalog do
description "Catalog description"
…
trait :with_courses do
after :create do |catalog|
courses = FactoryBot.create_list :course, 2
catalog.courses << courses
catalog.save
end
end
end
end