फैक्ट्री गर्ल में has_and_belongs_to_many एसोसिएशन कैसे बनाएं


119

निम्नलिखित को देखते हुए

class User < ActiveRecord::Base
  has_and_belongs_to_many :companies
end

class Company < ActiveRecord::Base
  has_and_belongs_to_many :users
end

आप कंपनियों और उपयोगकर्ताओं के लिए द्विदिश संघ सहित कारखानों को कैसे परिभाषित करते हैं? यहाँ मेरा प्रयास है

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

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

अब मैं कोशिश करता हूं

Factory :user

शायद अनजाने में यह एक अनंत लूप में परिणत होता है क्योंकि फैक्ट्रियां एक दूसरे का उपयोग खुद को परिभाषित करने के लिए करती हैं।

अधिक आश्चर्यजनक रूप से मुझे इस बात का उल्लेख नहीं मिला कि यह कैसे करना है, क्या आवश्यक कारखानों को परिभाषित करने के लिए एक पैटर्न है या मैं मौलिक रूप से कुछ गलत कर रहा हूं?

जवाबों:


132

यहाँ समाधान है कि मेरे लिए काम कर रहा है।

FactoryGirl.define do

  factory :company do
    #company attributes
  end

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

end

यदि आपको विशिष्ट कंपनी की आवश्यकता होगी तो आप इस तरह से कारखाने का उपयोग कर सकते हैं

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

आशा है कि यह किसी के लिए उपयोगी होगा।


4
धन्यवाद, सभी समाधानों में से सबसे साफ।
मिक

धन्यवाद। इसने घंटों की हताशा के बाद मेरी समस्या को ठीक कर दिया है।
टोनी बेनेट आक्ट

यह केवल मेरे लिए काम करता है जब सभी कारखाने एक फ़ाइल में होते हैं जो काफी अवांछनीय है। इसलिए नीचे दिए गए @ टॉप्स द्वारा उल्लिखित समाधान बेहतर प्रतीत होता है।
9

40

फ़ैक्टरीगर्ल तब से अपडेटेड है और अब इस समस्या को हल करने के लिए कॉलबैक शामिल हैं। अधिक जानकारी के लिए http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl पर एक नज़र डालें ।


37
लिंक वास्तव में यह नहीं कहता है कि has_and_belongs_to_many को कैसे संभालना है ... मैं यह नहीं देखता कि यह कैसे करना है ...
dmonopoly

3
कॉलबैक सिंटैक्स को अब बदल दिया गया है: फ़ैक्टरी गर्ल के after(:create)बजाय after_createजैसा कि यहाँ उल्लेख किया गया है: stackoverflow.com/questions/15003968/…
माइकल यगूदेव ने

22

मेरी राय में, बस दो अलग-अलग कारखानों का निर्माण करें जैसे:

 Factory.define: उपयोगकर्ता,: वर्ग => उपयोगकर्ता करें | यू |
  # बस सामान्य गुण इनिशियलाइज़ेशन
 समाप्त

 Factory.define: company,: class => कंपनी do | u |
  # बस सामान्य गुण इनिशियलाइज़ेशन
 समाप्त

जब आप उपयोगकर्ता के लिए परीक्षण-केस लिखते हैं तो बस इस तरह लिखें

 फैक्टरी (: उपयोगकर्ता,: कंपनियां => [फैक्टरी (: कंपनी)])

आशा है कि यह काम करेगा।


2
धन्यवाद, यह एकमात्र उदाहरण है जिससे मुझे काम मिल सकता है। फैक्ट्री गर्ल हैबिटम के लिए एक बड़ा सिरदर्द है।
jspooner

यह अब FactoryGirl के हाल के संस्करणों के साथ काम नहीं कर रहा है (मैं सोच रहा हूँ रेल 3)
Raf

9

मैं प्रदान की गई वेबसाइट पर उपर्युक्त मामले के लिए एक उदाहरण नहीं खोज सका। (केवल: एन और बहुरूपी assocations, लेकिन कोई habtm)। मेरे पास एक समान मामला था और मेरा कोड इस तरह दिखता है:

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
क्या होगा अगर गैर-शून्य उपयोगकर्ता गणना का सत्यापन है?
dfens

5

फैक्ट्री का उपयोग करते समय मेरे लिए जो काम किया गया था वह एसोसिएशन की स्थापना कर रहा था। अपने उदाहरण का उपयोग करना:

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

company.users << user 
company.save! 

4

इस तरह अच्छा और क्रिया मिला:

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)] }मेरी बहुत मदद करता है! धन्यवाद!
मोंटिरोब्रिना

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

चेतावनी: उपयोगकर्ता बदलें: [उपयोगकर्ता]: उपयोगकर्ता => [उपयोगकर्ता] रूबी 1.8.x के लिए


4
यह नहीं होना चाहिए: after_create { |company, evaluator| FactoryGirl.create_list(:user, evaluator.users_count, companies: [company]) }?
रफ

0

Habtm (इस बारे में और अधिक के बजाय के माध्यम से: सबसे पहले मैं दृढ़ता से has_many का उपयोग करने के लिए प्रोत्साहित करते हैं यहां ,) ताकि आप की तरह कुछ के साथ खत्म हो जाएगा:

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

इसके बाद आपके पास दोनों तरफ has_many एसोसिएशन होगा और उन्हें factory_girl में असाइन किया जा सकता है जिस तरह से आपने किया था।


3
ऐसा नहीं होना चाहिए Employment belongs_to :userऔर Employment belongs_to :companyएक उपयोगकर्ता के साथ एक कंपनी को जोड़ने वाले मॉडल के साथ?
डैनियल बर्ड्सले

5
आपके द्वारा बताए गए पोस्ट के माध्यम से एक त्वरित पढ़ने से मेरा निष्कर्ष यह है कि यह आपके उपयोग के मामले पर निर्भर करता है कि क्या habtm या has_many का चयन करें। कोई वास्तविक "विजेता" नहीं है।
auralbee

खैर, एचएमटी का उपयोग करते समय एकमात्र ओवरहेड यह है कि आपको आईडी को तालिका के माध्यम से परिभाषित करना होगा। अभी, मैं ऐसी स्थिति की कल्पना नहीं कर सकता जब कोई समस्या हो सकती है। मैं यह नहीं कहता कि habtm का कोई मतलब नहीं है, बस 99% उपयोग के मामलों में यह hmt (इसके फायदे के कारण) का उपयोग करने के लिए अधिक समझ में आता है।
मिलन नोवोटा

6
-1, सिर्फ इसलिए कि एचएमटी के अधिक 'फायदे' हैं इसका मतलब यह है कि आपको उन लाभों की आवश्यकता होने पर इसका उपयोग करना चाहिए। Pet peeve, क्योंकि मैं अब एक ऐसे प्रोजेक्ट पर काम कर रहा हूँ जहाँ डेवलपर ने कई मामलों में HMT का इस्तेमाल किया जहाँ HABTM ने पर्याप्त मात्रा में काम किया होगा। कोडबेस इसलिए बड़ा है, अधिक जटिल है, कम सहज है और इसकी वजह से धीमी SQL जुड़ता है। इसलिए, जब आप कर सकते हैं, तब एचएबीटीएम का उपयोग करें, तब जब आपको प्रत्येक संघ के बारे में अतिरिक्त जानकारी संग्रहीत करने के लिए एक अलग जॉइन मॉडल बनाने की आवश्यकता होती है, तभी एचएमटी का उपयोग करें।
सीबम

0

रेल के लिए अद्यतन 5:

has_and_belongs_to_manyएसोसिएशन का उपयोग करने के बजाय , आपको विचार करना चाहिए: has_many :throughएसोसिएशन।

इस एसोसिएशन के लिए उपयोगकर्ता कारखाना इस तरह दिखता है:

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

आप एक समान तरीके से कंपनी का कारखाना बना सकते हैं।

एक बार दोनों कारखाने स्थापित हो जाने के बाद, आप user_with_companiesकारखाने बना सकते हैं companies_count option। यहां आप यह निर्दिष्ट कर सकते हैं कि उपयोगकर्ता कितनी कंपनियों से संबंधित है:create(:user_with_companies, companies_count: 15)

आप फैक्ट्री गर्ल एसोसिएशन के बारे में विस्तृत विवरण यहां पा सकते हैं ।


0

HABTM के लिए मैंने लक्षण और कॉलबैक का उपयोग किया

कहो कि आपके पास निम्नलिखित मॉडल हैं:

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

आप ऊपर फैक्ट्री को परिभाषित कर सकते हैं :

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

आप संघों की सूची बनाने के लिए नए कारखाने को परिभाषित कर सकते हैं और (बाद में) कॉलबैक का उपयोग कर सकते हैं। आइए देखें कि इसे इस उदाहरण में कैसे करें:

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

संलग्नक company_count एक क्षणिक है और कारखाने की विशेषताओं में और मूल्यांकनकर्ता के माध्यम से कॉलबैक में उपलब्ध है। अब, आप उन कंपनियों के साथ एक उपयोगकर्ता बना सकते हैं जो यह निर्दिष्ट करने के लिए कि आप कितनी कंपनियां चाहते हैं:

create(:user_with_companies).companies.length # 10
create(:user_with_companies, companies_count: 15).companies.length # 15
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.