Factory kızda has_and_belongs_to_many ilişkileri nasıl oluşturulur


120

Aşağıdakiler göz önüne alındığında

class User < ActiveRecord::Base
  has_and_belongs_to_many :companies
end

class Company < ActiveRecord::Base
  has_and_belongs_to_many :users
end

çift ​​yönlü ilişki dahil olmak üzere şirketler ve kullanıcılar için fabrikaları nasıl tanımlarsınız? İşte benim girişimim

Factory.define :company do |f|
  f.users{ |users| [users.association :company]}
end

Factory.define :user do |f|
  f.companies{ |companies| [companies.association :user]}
end

şimdi deniyorum

Factory :user

Belki de şaşırtıcı olmayan bir şekilde, fabrikalar kendilerini tanımlamak için birbirlerini yinelemeli olarak kullandığından, bu sonsuz bir döngü ile sonuçlanır.

Daha şaşırtıcı bir şekilde bunun nasıl yapılacağına dair hiçbir yerde bir söz bulamadım, gerekli fabrikaları tanımlamak için bir kalıp var mı yoksa temelde yanlış bir şey mi yapıyorum?

Yanıtlar:


132

İşte benim için çalışan çözüm.

FactoryGirl.define do

  factory :company do
    #company attributes
  end

  factory :user do
   companies {[FactoryGirl.create(:company)]}
   #user attributes
  end

end

belirli bir şirkete ihtiyacınız varsa fabrikayı bu şekilde kullanabilirsiniz

company = FactoryGirl.create(:company, #{company attributes})
user = FactoryGirl.create(:user, :companies => [company])

Umarım bu birileri için yardımcı olur.


4
Teşekkürler, tüm çözümlerin çoğu temiz.
Mik

Teşekkür ederim. Bu, saatlerce süren hayal kırıklığından sonra sorunumu çözdü.
Tony Beninate

Bu sadece tüm fabrikalar oldukça istenmeyen bir şekilde tek bir dosyadayken işe yarıyor . Bu nedenle aşağıda @opsb tarafından belirtilen çözüm daha iyi görünüyor.
2013


22

Kanımca, aşağıdaki gibi iki farklı fabrika oluşturun:

 Factory.define: user,: class => Kullanıcı do | u |
  # Yalnızca normal öznitelikleri başlatma
 son

 Factory.define: company,: class => Company do | u |
  # Yalnızca normal öznitelikleri başlatma
 son

Kullanıcı için test senaryoları yazdığınızda, sadece şöyle yazın

 Fabrika (: kullanıcı,: şirketler => [Fabrika (: şirket)])

Umarım işe yarar.


2
Teşekkürler, çalışabileceğim tek örnek bu. Fabrika kızı habtm için büyük bir baş ağrısıdır.
jspooner

Bu, FactoryGirl'in son sürümlerinde artık çalışmıyor (Rails 3'ü düşünüyorum)
Raf

9

Sağlanan web sitesinde yukarıda belirtilen vaka için bir örnek bulamadım. (Yalnızca 1: N ve polimorfik ilişkiler, ancak habtm yok). Benzer bir durum yaşadım ve kodum şöyle görünüyor:

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

3
sıfır olmayan kullanıcı sayısının doğrulanması varsa ne olur?
dfens

5

Benim için işe yarayan şey, fabrikayı kullanırken birliği kurmaktı. Örneğinizi kullanarak:

user = Factory(:user)
company = Factory(:company)

company.users << user 
company.save! 

4

Bu şekilde güzel ve ayrıntılı buldum:

FactoryGirl.define do
  factory :foo do
    name "Foo" 
  end

  factory :bar do
    name "Bar"
    foos { |a| [a.association(:foo)] }
  end
end

1
foos { |a| [a.association(:foo)] }bana çok yardımcı oluyor! Teşekkür ederim!
monteirobrena

3
  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

Uyarı: Ruby 1.8.x için kullanıcıları değiştir: [user]: users => [user]


4
Olması gerekmez after_create { |company, evaluator| FactoryGirl.create_list(:user, evaluator.users_count, companies: [company]) }mi?
Raf 08

0

Her şeyden önce, habtm yerine has_many: through kullanmanızı şiddetle tavsiye ediyorum (bununla ilgili daha fazla bilgi burada ), böylece şöyle bir şey elde edeceksiniz:

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

Bundan sonra, her iki tarafta da has_many birliğiniz olacak ve sizin yaptığınız gibi factory_girl'de onlara atayabilirsiniz.


3
Olmaması gerektiğini Employment belongs_to :userve Employment belongs_to :companybir Kullanıcı ile bir Şirket bağlayan katılmak modeli ile?
Daniel Beardsley

5
Bahsettiğiniz gönderiyi hızlı bir şekilde okuduktan sonra, habtm veya has_many: through seçiminin sizin kullanım durumunuza bağlı olduğudur. Gerçek bir "kazanan" yoktur.
auralbee

Eh, hmt kullanırken tek ek yük, geçiş tablosunda tanımlanmış kimliğinizin olması gerektiğidir. Şu anda, herhangi bir soruna neden olabilecek bir durum hayal edemiyorum. Habtm'in hiçbir faydası olmadığını söylemiyorum, sadece% 99 kullanım durumlarında hmt kullanmanın (avantajları nedeniyle) daha mantıklı olduğunu söylemiyorum.
Milan Novota

6
-1, HMT'nin daha fazla 'avantajı' olduğu için, yalnızca bu avantajlara İHTİYACINIZ VARSA onu kullanmanız gerektiği anlamına gelir. Pet peeve, çünkü şu anda geliştiricinin HMT'yi HABTM'nin yeterli olacağı birkaç durumda kullandığı bir proje üzerinde çalışıyorum. Bu nedenle kod tabanı daha büyük, daha karmaşık, daha az sezgiseldir ve bu nedenle daha yavaş SQL birleşimleri üretir. Bu nedenle, yapabildiğiniz zaman HABTM kullanın, ardından her bir ilişkilendirme hakkında ek bilgi depolamak için ayrı bir birleştirme modeli oluşturmanız GEREKTİĞİNDE, yalnızca o zaman HMT kullanın.
sbeam

0

Rails 5 Güncellemesi:

has_and_belongs_to_manyİlişkilendirme kullanmak yerine şunu düşünmelisiniz: has_many :throughilişkilendirme.

Bu ilişkilendirmenin kullanıcı fabrikası şuna benzer:

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

Şirket fabrikasını da benzer şekilde oluşturabilirsiniz.

Her iki fabrika da ayarlandıktan sonra, user_with_companiesile fabrika oluşturabilirsiniz companies_count option. Burada kullanıcının kaç şirkete ait olduğunu belirtebilirsiniz:create(:user_with_companies, companies_count: 15)

Fabrika kız dernekleri ile ilgili detaylı açıklamayı burada bulabilirsiniz .


0

HABTM için özellikler ve geri aramalar kullandım .

Aşağıdaki modellere sahip olduğunuzu varsayalım:

class Catalog < ApplicationRecord
  has_and_belongs_to_many :courses
  
end
class Course < ApplicationRecord
  
end

Sen edebilirsiniz Fabrikası yukarıdaki tanımlar :

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

-1

Yeni fabrika tanımlayabilir ve (: oluştur) geri aramadan sonra ilişkilendirmeler listesi oluşturmak için kullanabilirsiniz. Bu örnekte nasıl yapılacağını görelim:

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

Companies_count niteliği geçicidir ve fabrikanın özelliklerinde ve değerlendirici aracılığıyla geri aramada mevcuttur. Artık, kaç şirket istediğinizi belirtme seçeneğiyle şirketlerle bir kullanıcı oluşturabilirsiniz:

create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 15
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.