form_for नेस्टेड संसाधनों के साथ


125

मेरे पास फ़ॉर्म_ फॉर और नेस्टेड संसाधनों के बारे में दो-भाग का प्रश्न है। मान लीजिए कि मैं एक ब्लॉग इंजन लिख रहा हूं और मैं एक लेख पर टिप्पणी करना चाहता हूं। मैंने एक नेस्टेड संसाधन को निम्न प्रकार से परिभाषित किया है:

map.resources :articles do |articles|
    articles.resources :comments
end

टिप्पणी फॉर्म शो के लिए है। लेख के लिए देखें। लेख के नीचे, उदाहरण के लिए, इस तरह से:

<%= render :partial => "articles/article" %>
<% form_for([ :article, @comment]) do |f| %>
    <%= f.text_area :text %>
    <%= submit_tag "Submit" %>
<%  end %>

यह एक त्रुटि देता है, "शून्य के लिए कॉल की गई आईडी, जो कि गलती से होगी आदि।" मैंने भी कोशिश की है

<% form_for @article, @comment do |f| %>

जो सही तरीके से प्रस्तुत करता है लेकिन f.text_area को टिप्पणी के बजाय लेख के 'पाठ' क्षेत्र से संबंधित करता है, और उस पाठ क्षेत्र में लेख के लिए html.text विशेषता प्रस्तुत करता है। इसलिए मुझे यह गलत भी लगता है। मैं जो चाहता हूं वह एक ऐसा रूप है जिसका 'सबमिट' कॉल करेगा, जिसमें एक्शन पर टिप्पणी / टिप्पणी / उदाहरण के लिए / लेख / 1 / टिप्पणियों के लिए, ParC में एक लेख_id के साथ CommentsController पर क्रिएट एक्शन होगा।

मेरे सवाल का दूसरा हिस्सा यह है कि शुरुआत करने के लिए टिप्पणी उदाहरण बनाने का सबसे अच्छा तरीका क्या है? मैं ArticleController की शो कार्रवाई में एक @comment बना रहा हूं, इसलिए एक टिप्पणी ऑब्जेक्ट form_for सहायक के लिए गुंजाइश में होगा। फिर CommentsController की कार्रवाई में, मैं form_for से पारित किए गए पैरामेट्स का उपयोग करके नया @comment बनाता हूं।

धन्यवाद!

जवाबों:


228

ट्रैविस आर सही है। (मुझे लगता है कि मैं फिर से आगे बढ़ सकता हूं।) मुझे सिर्फ यह काम करना चाहिए। इन मार्गों के साथ:

resources :articles do
  resources :comments
end

आपको रास्ते मिलते हैं:

/articles/42
/articles/42/comments/99

नियंत्रकों पर भेजा गया

app/controllers/articles_controller.rb
app/controllers/comments_controller.rb

बस के रूप में यह http://guides.rubyonrails.org/rout.html#nested-resources पर कहता है , जिसमें कोई विशेष नाम स्थान नहीं है।

लेकिन पक्षपात और रूप मुश्किल हो जाते हैं। वर्ग कोष्ठक पर ध्यान दें:

<%= form_for [@article, @comment] do |f| %>

सबसे महत्वपूर्ण, यदि आप एक यूआरआई चाहते हैं, तो आपको कुछ इस तरह की आवश्यकता हो सकती है:

article_comment_path(@article, @comment)

वैकल्पिक रूप से:

[@article, @comment]

http://edgeguides.rubyonrails.org/rout.html#creating-paths-and-urls-from-objects पर वर्णित

उदाहरण के लिए, comment_itemपुनरावृत्ति के लिए आपूर्ति के साथ आंशिक रूप से संग्रह के अंदर ,

<%= link_to "delete", article_comment_path(@article, comment_item),
      :method => :delete, :confirm => "Really?" %>

जमुरा जो कहते हैं, वह अनुच्छेद के संदर्भ में काम कर सकता है, लेकिन यह मेरे लिए विभिन्न अन्य तरीकों से काम नहीं करता है।

नेस्टेड संसाधनों से संबंधित बहुत चर्चा है, उदाहरण के लिए http://weblog.jamisbuck.org/2007/2/5/nesting-resources

दिलचस्प बात यह है कि मैंने अभी सीखा है कि ज्यादातर लोगों के यूनिट-टेस्ट वास्तव में सभी रास्तों का परीक्षण नहीं कर रहे हैं। जब लोग जैमिस्बक के सुझाव का पालन करते हैं, तो वे नेस्टेड संसाधनों पर पहुंचने के लिए दो तरीकों से समाप्त होते हैं। उनके यूनिट-परीक्षण आम तौर पर सरलतम / पोस्ट प्राप्त होंगे:

# POST /comments
post :create, :comment => {:article_id=>42, ...}

वे जिस मार्ग को पसंद कर सकते हैं उसका परीक्षण करने के लिए, उन्हें इस तरह से करने की आवश्यकता है:

# POST /articles/42/comments
post :create, :article_id => 42, :comment => {...}

मैंने इसे सीखा क्योंकि मेरे यूनिट-परीक्षण विफल हो गए जब मैंने इससे स्विच किया:

resources :comments
resources :articles do
  resources :comments
end

इसके लिए:

resources :comments, :only => [:destroy, :show, :edit, :update]
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end

मुझे लगता है कि डुप्लिकेट मार्गों का होना ठीक है, और कुछ यूनिट-परीक्षणों को याद करना है। (क्यों परीक्षण? क्योंकि यहां तक ​​कि अगर उपयोगकर्ता कभी भी डुप्लिकेट नहीं देखता है, तो आपके फॉर्म उन्हें संदर्भित कर सकते हैं, या तो निहित या नामित मार्गों के माध्यम से।) फिर भी, अनावश्यक दोहराव को कम करने के लिए, मैं यह सलाह देता हूं:

resources :comments
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end

लंबे उत्तर के लिए क्षमा करें। बहुत से लोगों को सूक्ष्मता के बारे में पता नहीं है, मुझे लगता है।


यह काम है लेकिन, मुझे कंट्रोलर को संशोधित करना पड़ा जैसे जामुरा ने कहा।
मार्कस बेकर

जाम का रास्ता काम करता है, लेकिन आप अतिरिक्त मार्गों के साथ समाप्त हो सकते हैं जिनके बारे में आप शायद नहीं जानते हैं। स्पष्ट होना बेहतर है।
cdunn2001

मेरे पास संसाधन, @result के अंदर @ नेस्टेड था। हालांकि, [@result, @course]काम किया है, लेकिन form_for(@result, url: { action: "create" }) यह भी काम करता है। इसके लिए केवल अंतिम मॉडल नाम और विधि नाम की आवश्यकता है।
अनवर

@ cdunn2001 क्या आप बता सकते हैं कि हमें यहाँ "@article" का उल्लेख क्यों करना है और इसका क्या अर्थ है? नीचे सिंटैक्स क्या करता है? : <% = form_for [@article, @comment] करते हैं | f | %>
अर्पित अग्रवाल

1
ट्रैविस / @ cdunn2001 ने इसे सही पाया। जब आप डुप्लिकेट के बिना नेस्टेड मार्गों का उपयोग कर रहे हों, तो माता-पिता और संसाधन दोनों को सेट न करें, अन्यथा यह सोचेंगे कि सभी क्रियाएं नेस्टेड हैं। इसी तरह अगर आपने सब कुछ नस्ट कर दिया है, तो हमेशा AT.parent सेट करें। इसके अलावा अगर आपके पास आंशिक रूप से नेस्टेड मार्गों के साथ रद्द बटन के साथ एक सामान्य रूप है, तो निम्न की तरह एक पथ का उपयोग करें ताकि यह आपके द्वारा निर्धारित किए गए काम पर ध्यान दें (बच्चे के बहुवचन पर ध्यान दें): <% = link_to 'रद्द करें', parent_drenren_path (AT.parent) || AT.child.parent)%>
iheggie

54

सुनिश्चित करें कि दोनों ऑब्जेक्ट्स कंट्रोलर में बनाए गए हैं: @postऔर @commentपोस्ट के लिए, जैसे:

@post = Post.find params[:post_id]
@comment = Comment.new(:post=>@post)

तब देखने में:

<%= form_for([@post, @comment]) do |f| %>

प्रपत्र में स्पष्ट रूप से सरणी को स्पष्ट रूप से परिभाषित करना सुनिश्चित करें, न कि अल्पविराम को अलग करें जैसे कि आपने ऊपर दिया है।


ट्रैविस थोड़ा पुराना जवाब है, लेकिन मेरा मानना ​​है कि यह रेल 3.2.X के लिए सबसे सही है। यदि आप चाहते हैं कि फॉर्म बिल्डर के सभी तत्व टिप्पणी क्षेत्रों को आबाद करने के लिए, बस एक सरणी का उपयोग करें, url सहायकों की आवश्यकता नहीं है।
कार्ल

1
केवल पैरेंट ऑब्जेक्ट सेट करें जहां कार्रवाई नेस्टेड है। यदि आप केवल आंशिक रूप से संसाधन को नस्ट करते हैं (उदाहरण के अनुसार), तो मूल ऑब्जेक्ट सेट करने से form_for विफल हो जाएगा (रेल के साथ पुन: पुष्टि की गई 5.1 अभी)
iheggie

35

आपको फॉर्म में विशेष चीजें करने की जरूरत नहीं है। आप केवल शो एक्शन में सही तरीके से टिप्पणी का निर्माण करते हैं:

class ArticlesController < ActionController::Base
  ....
  def show
    @article = Article.find(params[:id])
    @new_comment = @article.comments.build
  end
  ....
end

और फिर लेख देखने के लिए इसके लिए एक फॉर्म बनाएं:

<% form_for @new_comment do |f| %>
   <%= f.text_area :text %>
   <%= f.submit "Post Comment" %>
<% end %>

डिफ़ॉल्ट रूप से, यह टिप्पणी उस createकार्रवाई पर जाएगी CommentsController, जिसे आप संभवतः पृष्ठ में redirect :backवापस करने के लिए भेजना चाहते हैं Article


10
मुझे form_for([@article, @new_comment])प्रारूप का उपयोग करना था । मुझे लगता है कि यह इसलिए है क्योंकि मैं इसके लिए दृश्य दिखा रहा हूं comments#new, नहीं article#new_comment। मैं article#new_commentरेल में यह पता लगाने के लिए पर्याप्त स्मार्ट हूं कि टिप्पणी ऑब्जेक्ट में क्या निहित है और आपको इसे निर्दिष्ट करने की आवश्यकता नहीं है?
सूप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.