रेल्स: has_one एसोसिएशन बनाएं


100

हाय (विशाल नौसिखिया यहाँ), मेरे पास निम्न मॉडल हैं:

class Shop < ActiveRecord::Base
  belongs_to :user
  validates_uniqueness_of :title, :user_id, :message => "is already being used"
end

तथा

class User < ActiveRecord::Base
  has_one :shop, :dependent => :destroy
end

जब मैं एक नई दुकान बनाने वाला होता हूं, मुझे निम्नलिखित त्रुटि मिलती है:

private method `create' called for nil:NilClass

यह मेरा नियंत्रक है:

@user = current_user
@shop = @user.shop.create(params[:shop])

मैंने यहां और वहां गाइड और ट्यूटोरियल पढ़कर विभिन्न बदलावों की कोशिश की है, लेकिन मैं पहले की तुलना में अधिक भ्रमित हूं और इसे काम करने के लिए नहीं मिल सकता। किसी भी तरह की सहायता का स्वागत किया जाएगा।


प्रश्न को प्रतिबिंबित करने के लिए संपादित प्रश्न शीर्षक। रेलिंग में has_one एसोसिएशन के साथ बिल्ड
मार्क-एंड्रे लाफ्यून

1
तुम भी उपयोग कर सकते हैं@user.build_shop(params)
ImranNaqvi

जवाबों:


123

सबसे पहले, यहाँ है कि आप क्या चाहते हैं:

@user = current_user
@shop = Shop.create(params[:shop])
@user.shop = @shop

अब यहाँ आपके संस्करण ने काम क्यों नहीं किया:

आपने शायद सोचा था कि यह काम कर सकता है क्योंकि यदि उपयोगकर्ता has_manyका शॉप से ​​संबंध था , @user.shops.create(params[:shop]) तो काम करेगा । हालाँकि has_manyसंबंधों और has_oneसंबंधों के बीच एक बड़ा अंतर है :

has_manyरिलेशन के साथ , shopsActiveRecord संग्रह ऑब्जेक्ट लौटाता है, जिसमें ऐसी विधियाँ हैं जिनका उपयोग आप किसी उपयोगकर्ता से / से दुकानें जोड़ने और हटाने के लिए कर सकते हैं। उन तरीकों में से एक है create, जो एक नई दुकान बनाता है और इसे उपयोगकर्ता में जोड़ता है।

एक has_oneसंबंध के साथ , आपको इस तरह के संग्रह की वस्तु वापस नहीं मिलती है, लेकिन बस उपयोगकर्ता को जो दुकान वस्तु है - या यदि उपयोगकर्ता के पास अभी तक कोई दुकान नहीं है तो वह शून्य है। चूंकि न तो शॉप ऑब्जेक्ट्स और न ही एक createविधि है, आप createइस तरह से has_oneसंबंधों के साथ उपयोग नहीं कर सकते ।


आपके उत्तर के लिए धन्यवाद, sepp2k। अब मैं देख रहा हूं कि मेरा कोड काम क्यों नहीं कर सका।
नेको

118
आप भी इस्तेमाल कर सकते हैं @user.create_shop(params[:shop])Has_one द्वारा जोड़े गए तरीके देखें ।
नितंब

जवाब काम करता है, लेकिन @ समाधान भी काम करता है। आप दोनों को +1।
nfriend21

+1 का उत्तर क्योंकि मैं वही सोच रहा था, यह समझाने के लिए +1 और सर्वश्रेष्ठ समाधान देने के लिए टिप्पणी करने के लिए +1 क्यों।
जूल

224

ऐसा करने के लिए एक और अधिक संक्षिप्त तरीका है:

@user.create_shop(params[:shop])

रूबी गाइड्स पर रूबी में has_one द्वारा जोड़े गए तरीके देखें ।


6
यह निश्चित रूप से अधिक बेहतर दृष्टिकोण है
मैग्नम

7
सावधान रहें कि यदि आप एक से अधिक बार create_shop करते हैं तो वह पिछली दुकान को हटा देगा। उदाहरण के लिए यदि आप @user.create_shop(params[:shop_one_info])इसे चलाते हैं तो shop_one बना लेंगे, लेकिन यदि आप चलाते हैं @user.create_shop(params[:shop_two_info])कि यह पहली दुकान को हटा देगा और दूसरा बना देगा।
इकोडिंग

पिछली दुकान को हटाने के बारे में उपरोक्त टिप्पणी रेल 3.2.18 के लिए है, अधिक हाल के संस्करणों के बारे में नहीं जानते। 5 मिनट के बाद टिप्पणी संपादित नहीं कर सकते -_-
ecoding5

एक समाधान मिला, मैंने संबंधित मॉडल पर विशिष्टता स्थापित नहीं की है, इसलिए सुनिश्चित करें कि आप इस उदाहरण के शॉप मॉडल में इसे कैसे सेट करते हैं।
इकोडिंग

आप उपयोग कर सकते हैं@user.build_shop(params)
इमराननवी जुवे

7

यदि आप saveइसके बजाय दो और तरीके चाहते हैं create:

shop = @user.build_shop
shop.save

shop = Show.new
shop.user = @user
shop.save

1

बस उपरोक्त उत्तरों को जोड़ने के लिए -

@user.create_shop(params[:shop])

सिंटैक्स के ऊपर नया रिकॉर्ड बनता है, लेकिन यह बाद में इसी तरह के मौजूदा रिकॉर्ड को हटा देता है।

वैकल्पिक रूप से, यदि आप डिलीट कॉलबैक को ट्रिगर नहीं करना चाहते हैं

Shop.create(user_id: user.id, title: 'Some unique title')

यह धागा मददगार हो सकता है। यहाँ क्लिक करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.