2010-05-09 11 views
5

संक्षिप्तता के लिए मेरे सवाल का संपादन और अद्यतन करने के लिए मैं क्या किया है:मैं accepts_nested_attributes_for का उपयोग कैसे करूं?

मैं एक कंपनी के लिए एक से अधिक पते होने कैसे मॉडल और एक संपर्क के लिए एक एकल पता निर्दिष्ट करते हैं, और जब बनाने के लिए उन्हें प्रदान करने में सक्षम हो या एक संपर्क संपादित करना?

मैं एक नए संपर्क बनाने के समय एक पता जोड़ने के लिए सक्षम होने के लिए नेस्टेड विशेषताओं का उपयोग करना चाहते हैं। वह पता अपने मॉडल के रूप में मौजूद है क्योंकि मैं स्क्रैच से प्रवेश करने के बजाय मौजूदा पते से ड्रॉप-डाउन करने का विकल्प चाहता हूं।

मैं यह काम करने के लिए नहीं कर पा रहे। NilClass त्रुटि

यहाँ संपर्क के लिए मेरे मॉडल है:

class Contact < ActiveRecord::Base 
    attr_accessible :first_name, :last_name, :title, :phone, :fax, :email, :company, 
        :date_entered, :campaign_id, :company_name, :address_id, :address_attributes 

    belongs_to :company 
    belongs_to :address 
    accepts_nested_attributes_for :address 
end 

यहाँ पता के लिए मेरे मॉडल है:

class Address < ActiveRecord::Base 
    attr_accessible :street1, :street2, :city, :state, :zip 

    has_many :contacts 
end 

मैं चाहते हैं, जब मैं एक अपरिभाषित विधि `निर्माण 'शून्य के लिए मिलता है एक नया संपर्क बनाना, कंपनी के अन्य संपर्कों से संबंधित सभी पते तक पहुंचें।

class Company < ActiveRecord::Base 
    attr_accessible :name, :phone, :addresses 

    has_many :contacts 

    has_many :addresses, :through => :contacts 

end 

यहाँ कैसे मैं संपर्क के लिए _form के लिए दृश्य में एक क्षेत्र बनाने के लिए इतना है कि, जब कोई एक नया संपर्क बनाता है, वे पता मॉडल को पता पारित कोशिश कर रहा हूँ है: तो यहाँ कैसे मैं कंपनी का प्रतिनिधित्व करते है और संपर्क करने के लिए कि पते को संबद्ध:

<% f.fields_for :address, @contact.address do |builder| %> 
    <p> 
    <%= builder.label :street1, "Street 1" %> </br> 
    <%= builder.text_field :street1 %> 
    <p> 
    <% end %> 

जब मैं संपादित करने के लिए प्रयास करते हैं, स्ट्रीट 1 के लिए क्षेत्र को खाली है। और मुझे नहीं पता कि show.html.erb से मूल्य कैसे प्रदर्शित करें।

तल में मेरी त्रुटि कंसोल है - पता तालिका में मान बनाने के लिए प्रतीत नहीं कर सकते हैं:

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

def new 
    @contact = Contact.new 
    @contact.address.build # Iundefined method `build' for nil:NilClass 

    @contact.date_entered = Date.today 
    @campaigns = Campaign.find(:all, :order => "name") 
    if params[:campaign_id].blank? 

    else 
     @campaign = Campaign.find(params[:campaign_id]) 
     @contact.campaign_id = @campaign.id 
    end 

    if params[:company_id].blank? 

    else 
     @company = Company.find(params[:company_id]) 
     @contact.company_name = @company.name 
    end 

    end 

    def create 
    @contact = Contact.new(params[:contact]) 
    if @contact.save 
     flash[:notice] = "Successfully created contact." 
     redirect_to @contact 
    else 
     render :action => 'new' 
    end 
    end 

    def edit 
    @contact = Contact.find(params[:id]) 
    @campaigns = Campaign.find(:all, :order => "name") 
    end 

यहाँ का एक टुकड़ा है मेरी त्रुटि कंसोल: मैं विशेषता पोस्ट कर रहा हूँ, लेकिन यह पता तालिका में नहीं बना रहा है ....

प्रसंस्करण ContactsController # करोड़ { "प्रतिबद्ध" => "भेजें", "authenticity_token" => "d8/gx0zy0Vgg6ghfcbAYL0YtGjYIUC2b1aG +:

[पोस्ट] पैरामीटर (2010-05-12 21:16:17 पर 127.0.0.1 के लिए) eate डीडीकेजूएस = ", " संपर्क "=> {" company_name "=>" सहयोगी ", " शीर्षक "=>" "," campaign_id "=>" 2 ", " address_attributes "=> {" street1 "=> "एबीसी"}, "फैक्स" => "", "फोन" => "", "last_name" => "", "date_entered" => "2010-05-12", "ईमेल" = > "", "first_name" => "abc"}}

कंपनी लोड (0.0ms) [0 मी [0mSELECT * "कंपनियों" से कहां ("कंपनियां"। "नाम" = 'सहयोगी') LIMIT 1 [0m

पता बनाएं (16।0ms) [0m
[0; 1mINSERT में "पतों" ("शहर", "ज़िप", "created_at", "street1", "updated_at", "street2", "राज्य") मूल्यों (शून्य, शून्य, '2010-05-13 04:16:18', शून्य, '2010-05-13 04:16:18', शून्य, शून्य) [0m

संपर्क बनाएँ (0.0ms) [0m
[0mINSERT में "संपर्क" ("कंपनी", "created_at", "शीर्षक", "updated_at", "CAMPAIGN_ID", "address_id", "last_name", "फोन", "फैक्स", " company_id "," date_entered ", " first_name "," ईमेल ") VALUES (NULL, '2010-05-13 04:16:18', '', '2010-05-13 04:16:18', 2, 2, '', '', '', 5, '2010- 05-12 ',' एबीसी ',' ') [0 मिनट

+0

हम्म मुझे लगता है कि, पता तालिका में insers मूल्य बनाता है यहाँ जहां पता (16.0ms) [0m [0 बनाएं है, 1mINSERT में "पतों" ("शहर", "ज़िप", "created_at", "street1 "," अपडेट_ट "," स्ट्रीट 2 "," स्टेट ") वैल्यूज (न्यूल, न्यूल, '2010-05-13 04:16:18', न्यूल, '2010-05-13 04:16:18', न्यूल, नल) [0 एम – dombesz

+0

मेरी पोस्ट अपडेट की गई, विचारों में कोड शामिल किया गया। – dombesz

+0

आप देख सकते हैं कि पता के तहत street1 के लिए मान बनाएं खाली हैं ... नहीं "abc" .... – Angela

उत्तर

3

बस एक साधारण सवाल, यदि आप इसे अपने संपर्क फ़ॉर्म में उपयोग करते हैं तो उसे एकवचन में पता नहीं होना चाहिए?

<% f.fields_for :address, @contact.address do |builder| %> 
    <p> 
    <%= builder.label :street1, "Street 1" %> </br> 
    <%= builder.text_field :street1 %> 
    <p> 
<% end %> 

अपनी कार्रवाई में आप

@ycontact.build_address 

करने के लिए यदि आप स्रोत कोड अपने इनपुट क्षेत्र की तरह दिखना चाहिए को देखें, तो भी की है।

< इनपुट type = "text" आकार = "30" नाम = "संपर्क [address_attributes] [street1]" आईडी = "contact_address_attributes_street1">

मुझे लगता है कि आप भी समस्याएं आ रही हैं अपने संघों, यदि आप तो

class Contact < ActiveRecord::Base 
    belongs_to :address 
    accepts_nested_attributes_for :address 
end 

class Address < ActiveRecord::Base 
    attr_accessible :street1 
    has_many :contacts 
end 

संपर्क में address_id की दुकान और मुझे लगता है कि यह अपने मामले क्योंकि आप एकाधिक संपर्कों के लिए एक पता प्रदान करना चाहते हैं है। इस मामले में

class Contact < ActiveRecord::Base 
    has_one :address 
    accepts_nested_attributes_for :address 
end 

class Address < ActiveRecord::Base 
    attr_accessible :street1 
    belongs_to :contact 
end 

आप नहीं कर सकते एक ही पते के साथ उपयोगकर्ताओं है:

तुम भी अगर आप अपना पता मॉडल में अपने contact_id की दुकान, उलटा में कर सकते हैं।

अद्यतन

अपने उपयोगकर्ता में show.html.eb आप

<%= @contact.address.street1 %> 

उपयोग कर सकते हैं अपनी कंपनी के show.html.erb में आप की तरह पते प्रदर्शित कर सकते हैं:

<% @company.addresses.each do |address| %> 
    <%= address.street1 %> 
    ... 
<% end %> 

आपके उपयोगकर्ता संपादन पृष्ठ पर फॉर्म फ़ील्ड new.html.erb जैसा ही होना चाहिए, बस फ़ॉर्म टैग जैसा दिखना चाहिए:

<% form_for @contact do |form| %> 
    <%=render :partial=>'fields' %> 
<% end %> 

क्षेत्रों आंशिक साथ togheter अपने सभी fieds शामिल हैं:

<% f.fields_for :address, @contact.address do |builder| %> 
    <p> 
    <%= builder.label :street1, "Street 1" %> </br> 
    <%= builder.text_field :street1 %> 
    <p> 
<% end %> 

यह काम करना चाहिए।

अद्यतन 2

आप सभी पते जिसके साथ एक कंपनी के हैं पहुँच सकते हैं:

@company.addresses 

आप

class Company<Activerecord::Base 
    has_many :contacts 
    has_many :addresses, :through=>:contacts 
end 

ड्राफ्ट, या डिफ़ॉल्ट पतों के बारे में है। आपकी जरूरतों के आधार पर आपके पास अलग-अलग विकल्प हो सकते हैं। मैं आपको विकल्प चाहता हूं कि एक संपर्क डेटाबेस से मौजूदा पते में से एक का चयन कर सके।

<%= form.select :address_id, options_from_collection_for_select(@company.addresses, 'id', 'street1')%> 

इसके अलावा, आप जोड़ सकते हैं या पते के रूप दूर करने के लिए, उस मामले में उपयोगकर्ता मौजूदा पतों में से एक चुनता है कुछ फैंसी जावास्क्रिप्ट का उपयोग कर सकते हैं: आप की तरह अपने संपर्क फार्म में एक सलेक्ट बॉक्स कर सकते हैं। इस मामले में आपको फॉर्म से address_attributes को हटाना होगा। मैं जावास्क्रिप्ट कोड के साथ एक लिंक बनाने का सुझाव देता हूं जो address_attributes जोड़ता है और हटाता है (टॉगल शैली)।

+0

खैर, मैं उन उपयोगकर्ताओं को रखना चाहता हूं जिनके पास एक ही पता है। लेकिन कई पते संभव हैं ... विभिन्न कर्मचारियों के साथ एक बड़ी, वितरित कंपनी की कल्पना करें। तो यह काम करेगा .... यह उपयोग कर रहा है: through =>: संपर्क, सही? – Angela

+0

भी ... accepts_nested_attributes_for करता है: संपर्क contact_to: पता होने पर पता काम करता है? मुझे लगता है कि मुझे एक त्रुटि मिलती है .... मुझे लगता है कि यह केवल has_many या has_one के लिए काम करता है .... मैंने – Angela

+0

प्रश्न को सरल बनाने के लिए अपना प्रश्न अपडेट किया है accepts_nested_attributes_for संबंधित_to के साथ भी काम करता है, मैं अभी इसका उपयोग कर रहा हूं। Has_many: इससे कोई फर्क नहीं पड़ता जब तक आप कंपनी मॉडल के माध्यम से पते बनाना नहीं चाहते हैं। वास्तव में भी समझ में नहीं आता है। – dombesz

1

प्रत्येक पता करने के लिए केवल एक ही संपर्क, (एक घर का पता) के अंतर्गत आता है, तो आप कर सकता है:

class Company < ActiveRecord::Base 
    has_many :contacts 
end 

class Contact < ActiveRecord::Base 
    belongs_to :company 
    has_one :address 
end 

class Address < ActiveRecord::Base 
    belongs_to :contact 
end 
बेशक

, आप केवल पता कॉलम को संपर्क तालिका में ले जा सकते हैं और पता मॉडल से पूरी तरह से छुटकारा पा सकते हैं।

class Company < ActiveRecord::Base 
    has_many :contacts 
end 

class Contact < ActiveRecord::Base 
    belongs_to :company 
    belongs_to :address 
end 

class Address < ActiveRecord::Base 
    has_many :contacts 
end 

आप company.addresses पाने के लिए एक has_many :through संघ में जोड़ सकते हैं:

प्रत्येक पता एकाधिक संपर्कों है (यानी, पतों कंपनी सुविधाओं जहां संपर्कों काम कर रहे हैं)

class Company < ActiveRecord::Base 
    has_many :contacts 
    has_many :addresses, :through => :contacts 
end 

दोनों में परिस्थितियों में पता घटक (सड़क, शहर, राज्य, आदि) पते तालिका में कॉलम हैं।

आपके प्रश्न का अंतिम भाग वास्तव में डेटा वितरण पर निर्भर करता है - यदि आपके पास केवल कुछ पते हैं, तो आप उन्हें मुख्य पते के साथ डिफ़ॉल्ट पते के साथ चुनिंदा तत्व में चिपका सकते हैं। अधिक पतों के साथ आपको स्वत: पूर्ण के साथ एक AJAXified फ़ॉर्म की आवश्यकता हो सकती है जो पते तालिका को खोजती है।

अपने तालिकाओं में नए संपर्क/पते प्राप्त करने के लिए, आप नेस्टेड रूपों को देखना चाहेंगे। Railscast 196 एक अच्छा परिचय है।

संपादित करें - के बारे में नेस्ट अधिक विशेषताओं

accepts_nested_attributes_for या तो एक has_many या has_one एसोसिएशन के साथ काम करना चाहिए, नहीं मिल पाता के कई स्तरों के साथ काम करना चाहिए। ऐसा लगता है कि आप एक से संपर्क करना चाहते हैं एक कंपनी के हैं, और कोई पता एक संपर्क के हैं, लेकिन ऐसी स्थिति में:

class Company < ActiveRecord::Base 
    has_many :contacts 
    accepts_nested_attributes_for :contact 
end 

class Contact < ActiveRecord::Base 
    belongs_to :company 
    has_one :address # or has_many, if you prefer 
end 

class Address < ActiveRecord::Base 
    belongs_to :contact 
end 
तब दृश्य उपयोग form_for में

और fields_for Railscast में वर्णित के रूप पाने के लिए नेस्टेड फॉर्म तत्व। यदि आपका फॉर्म असामान्य है तो यह सही होने के लिए थोड़ा मुश्किल हो सकता है। रायनब here से उत्कृष्ट उदाहरण हैं जो कई विशिष्ट स्थितियों को कवर करते हैं।

+0

हाय वहाँ! रेल व्यंजनों में वर्णित अनुसार, यह पॉलिमॉर्फिक का उपयोग करने से अलग कैसे होगा? प्रत्येक पते में वास्तव में कई संपर्क संभावित रूप से होते हैं; और इसलिए प्रत्येक कंपनी के पास कई पते हैं .... धन्यवाद। – Angela

+0

हाय, ऐसा प्रतीत नहीं होता है कि मैं एक स्वीकार्य + _nested_attribute_for का उपयोग कर सकता हूं: संपर्क मॉडल में accepts_nested_attributes_for के रूप में: पते क्योंकि यह एक related_to एसोसिएशन है। मैंने एपीआई को देखा और कोशिश कर रहा हूं ... लेकिन क्या यह सही है? – Angela

+0

पॉलिमॉर्फिक एसोसिएशन उपयोगी होते हैं जब आप अन्य मॉडल (जैसे कंपनी और व्यक्ति, उदाहरण के लिए) के साथ मॉडल (जैसे पता) साझा करना चाहते हैं। एक कंपनी के पास एक पता हो सकता है, और एक व्यक्ति के पास पता हो सकता है, इसलिए अगर पता प्रारूप समान है तो मॉडल का पुन: उपयोग करना समझ में आता है। बहुरूपता के बिना आपको अलग कंपनी एड्रेस और पर्सन एड्रेस मॉडल की आवश्यकता होगी। मैं आपकी अन्य टिप्पणी का जवाब देने के लिए उत्तर संपादित करूंगा। – zetetic

0

मैं सलाह देता हूं कि संपर्क में कई पते हों। यह जंगली में वैसे भी होता है।अगर केवल एक के लिए फैसला किया है, कि has_one :address

ओह होगा और आप उन्हें downcase चाहिए: has_many :Contactshas_many :contacts

पता मॉडल आप के साथ संदर्भ में होना चाहिए (डेटाबेस एक addressable_id और addressable_type क्षेत्र की जरूरत है)

belongs_to :addressable, :polymorphic => true 
+0

पता किसी नए संपर्क में कैसे जोड़ा जाएगा, फिर उस कंपनी के नए भावी संपर्क हिस्से में उपलब्ध होगा? – Angela

1

चूंकि आप एक कंपनी और संपर्क दोनों के लिए एक पता चाहते हैं, तो आपके पास दो विकल्प हैं। यदि आपको कभी भी कई पते की आवश्यकता नहीं है (जिसे मैं मानने के खिलाफ अनुशंसा कर सकता हूं), तो आप कंपनी और संपर्क दोनों में "belong_to: पता" डाल सकते हैं। पते के बाद "has_many: Companies" और "has_many: संपर्क" दोनों होंगे।

बेहतर विकल्प जो अधिक समझ में आता है, पॉलिमॉर्फिक एसोसिएशन का उपयोग करना है, जहां पता तालिका होगी: addressable_type और: addressable_id कॉलम या तो मॉडल से लिंक करने के लिए।

class Company < ActiveRecord::Base 
    attr_accessible :name, :phone, :addresses 

    has_many :contacts 
    accepts_nested_attributes_for :contacts 

    has_many :addresses, :as => :addressable 
    accepts_nested_attributes_for :addresses 

end 

class Contact < ActiveRecord::Base 
    attr_accessible :first_name, :last_name, :title, :phone, :fax, :email, :company, 
        :date_entered, :campaign_id, :company_name 

    belongs_to :company 
    has_many :addresses, :as => :addressable 
    accepts_nested_attributes_for :addresses 
end 

class Address < ActiveRecord::Base 
    attr_accessible :street1 

    belongs_to :addressable, :polymorphic => true 
end 

अब आप अपने मुसीबत एक भी संघ "company.addresses" दोनों यह पता है और उसके संपर्कों के उन प्राप्त करने के लिए करना चाहते हैं के साथ आता है। मैं इस से दूर रहने और एक अलग दृष्टिकोण का उपयोग करने की सलाह दे सकता हूं।

आप सही रिकॉर्ड करने के लिए ध्यान में रखते हुए उन पतों मैप करना चाहते करने जा रहे हैं, तो यह उन्हें अलग करने के लिए सबसे अच्छा हो सकता है:

<% form_for @company do |company_form| %> 
    <% company_form.fields_for :addresses do |address_form| %> 
    <%= address_form.text_field :street1 %> 
    <% end %> 
    <% company_form.fields_for :contacts do |contact_form| %> 
    <% contact_form.fields_for :addresses do |contact_address_form| %> 
     <%= contact_address_form.text_field :street1 %> 
    <% end %> 
    <% end %> 
<% end %> 

आपका पता तालिका इस तरह बहुरूपी स्तंभ हैं:

class CreateAddresses < ActiveRecord::Migration 
    def self.up 
    create_table :addresses do |t| 
     t.string :street1 
     t.string :addressable_type 
     t.integer :addressable_id 
     t.timestamps 
    end 
    end 

    def self.down 
    drop_table :addresses 
    end 
end 

मुझे यकीन नहीं है कि अगर आप इस तरह के रिकॉर्ड को अलग-अलग नहीं करते हैं तो आप सभी लिंकिंग सीधे कैसे रख सकते हैं।

यदि आपको प्रदर्शन उद्देश्यों के लिए किसी कंपनी के लिए सभी पते प्राप्त करने की आवश्यकता है, तो आप उन्हें इकट्ठा करने के लिए एकत्रित मानक रूबी गणना करने योग्य कुशलता का उपयोग कर सकते हैं।

शुभकामनाएं!

+0

हाय, मैं अभी भी यह तय करने की कोशिश कर रहा हूं कि पॉलिमॉर्फिक का उपयोग करना है या नहीं ...अवधारणात्मक रूप से, कंपनी के पास पते हैं: संपर्कों के माध्यम से ... दूसरे शब्दों में, एकमात्र कारण है कि मेरे पास एक कंपनी से जुड़ा एक पता है क्योंकि एक संपर्क संबंधित है। उसके बारे में क्या ख़याल है? – Angela

+0

हाँ, मुझे सभी कंपनी को देखने की ज़रूरत है। एड्रेस ... यह उपयोगकर्ता को एक नया संपर्क जोड़ने के दौरान एक संभावित पता चुनने की अनुमति देगा .... तो क्या इसका अर्थ बहुरूपता का उपयोग नहीं करना चाहिए? – Angela

+0

पॉलिमॉर्फिज्म समझ में आता है क्योंकि यदि आपका ऐप बढ़ता है तो आप अन्य ऑब्जेक्ट्स के साथ पते को जोड़ना चाहते हैं। यदि आप इसे पूर्ववत नहीं करते हैं, तो यह आवश्यक नहीं है। यदि आप पॉलिमॉर्फिज्म का उपयोग नहीं करते हैं, तो आप has_many का उपयोग कर सकते हैं: के माध्यम से, लेकिन केवल प्रदर्शन उद्देश्यों के लिए। किसी कंपनी के संपर्कों के पते को जोड़ने/संशोधित करने के लिए आपको अभी भी एक विशिष्ट संपर्क तक पहुंचने के लिए नेस्टेड रूपों का उपयोग करने की आवश्यकता होगी। पीएस क्या यह वोट के लिए पर्याप्त सहायक था? – aceofspades

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^