2010-09-10 5 views
7

config/routes.rb में:क्या किसी के पास रेल 3 में पॉलिमॉर्फिक नेस्टेड संसाधनों के प्रबंधन के लिए कोई सुझाव है?

resources :posts do 
    resources :comments 
end 

resources :pictures do 
    resources :comments 
end 

मैं भी इस पर टिप्पणी कर के लिए और अधिक चीजों के लिए अनुमति देने के लिए करना चाहते हैं।

मैं वर्तमान में mongoid का उपयोग कर रहा हूं (mongomapper रेल 3 के साथ संगत नहीं है जैसा कि मैं चाहूंगा), और टिप्पणियां एक एम्बेडेड संसाधन हैं (mongoid पॉलिमॉर्फिक रिलेशनल संसाधनों को अभी तक संभाल नहीं सकता है), जिसका अर्थ है कि मैं करता हूं टिप्पणी खोजने के लिए मूल संसाधन की आवश्यकता है।

if params[:post_id] 
    parent = Post.find(params[:post_id] 
else if params[:picture_id] 
    parent = Picture.find(params[:picture_id] 
end 

जो अगर गंदा होने वाली है:

मेरी नियंत्रक में, मैं टिप्पणी खोजने से पहले माता-पिता को खोजने की जरूरत:

वहाँ किसी भी सुरुचिपूर्ण तरीके निम्न समस्याओं में से कुछ को संभालने के लिए कर रहे हैं मैं टिप्पणी करने योग्य होने के लिए और चीजों को जोड़ना शुरू करता हूं।

इसके अलावा url_for([comment.parent, comment]) काम नहीं करता है, इसलिए मैं अपने Comment मॉडल में कुछ को परिभाषित करने के लिए जा रहा हूँ, लेकिन मुझे लगता है मैं भी Comment मॉडल में एक सूचकांक मार्ग परिभाषित करने की जरूरत करने जा रहा हूँ साथ ही संभावित एक संपादित करें और नई मार्ग परिभाषा।

ऐसे कई मुद्दे हो सकते हैं जिनसे मुझे आगे बढ़ने के साथ निपटना होगा।

मैं कल्पना नहीं कर सकता कि मैं इस समस्या को हल करने और हल करने वाला पहला व्यक्ति हूं, क्या यह और अधिक प्रबंधनीय बनाने के लिए वहां कोई समाधान है?

उत्तर

4

मुझे अपने ऐप में कुछ ऐसा करना था। मैंने जो कुछ लिया उसके साथ मैंने इसे थोड़ा सा बदल दिया, लेकिन मैंने इसका परीक्षण नहीं किया है, इसलिए देखभाल के साथ उपयोग करें। यह सुंदर नहीं है, लेकिन यह किसी और चीज से बेहतर है जिसे मैं सोचने में सक्षम था।

routes.rb में:

resources :posts, :pictures 

controller :comments do 
    get '*path/edit' => :edit, :as => :edit_comment 
    get '*path'  => :show, :as => :comment 
    # etc. The order of these is important. If #show came first, it would direct /edit to #show and simply tack on '/edit' to the path param. 
end 

comment.rb में:

parent_type, parent_id, scrap, id = params[:path].split '/' 

# Security: Make sure people can't just pass in whatever models they feel like 
raise "Uh-oh!" unless %w(posts pictures).include? parent_type 

@parent = parent_type.singularize.capitalize.constantize.find(parent_id) 
@comment = @parent.comments.find(id) 

ठीक है, से अधिक कुरूपता:

embedded_in :commentable, :inverse_of => :comments 

def to_param 
    [commentable.class.to_s.downcase.pluralize, commentable.id, 'comments', id].join '/' 
end 

एक में comments_controller.rb में फिल्टर से पहले। अब आप जो भी मॉडल चाहते हैं उसे टिप्पणियां जोड़ सकते हैं, और बस:

edit_comment_path @comment 
url_for @comment 
redirect_to @comment 

और इसी तरह।

संपादित करें: मैं अपने अनुप्रयोग में किसी भी अन्य रास्तों को लागू नहीं किया क्योंकि मैं जरूरत संपादित करें और अपडेट था, लेकिन मैं कल्पना करता है कि वे कुछ इस तरह दिखाई चाहते हैं:

controller :comments do 
    get '*path/edit' => :edit, :as => :edit_comment 
    get '*path'  => :show, :as => :comment 
    put '*path'  => :update 
    delete '*path'  => :destroy 
end 

अन्य कार्यों ट्रिकियर होगा। आप शायद की तरह कुछ करने की आवश्यकता होगी: [: PARENT_TYPE] और पैरामीटर [: PARENT_ID]

get ':parent_type/:parent_id/comments'  => :index, :as => :comments 
    post ':parent_type/:parent_id/comments'  => :create 
    get ':parent_type/:parent_id/comments/new' => :new, :as => :new_comment 

फिर आप पैरामीटर का उपयोग कर नियंत्रक में माता पिता के मॉडल का उपयोग होगा।तुम भी यूआरएल सहायकों के लिए उचित पैरामीटर पास पूरे करने होंगे:

comments_path('pictures', 7) 
+0

यह वास्तव में बहुत अच्छा लग रहा है; कुछ छोटे बदलावों के साथ मैंने अभी इसे लागू किया है, और अधिकांश भाग के लिए यह ठीक काम कर रहा है। आपके द्वारा पहले भाग में उपयोग की जाने वाली रूटिंग ट्रिकरी के लिए प्रलेखन कहां है, इसलिए मैं यह समझ सकता हूं कि कैसे बनाएं, अपडेट, डिलीट और इंडेक्स मार्गों को कैसे कनेक्ट करें? – Ryan

+0

ठीक है, मुझे लगता है कि मैंने यह पता लगाया कि आप क्या कर रहे थे और आप इसे बदसूरत क्यों पाते हैं। टिप्पणी मूल रूप से परिभाषित अंतिम मार्ग होने की आवश्यकता है क्योंकि यह कुछ भी मेल खाएगा। मैं जो कुछ भी कर रहा था उसका हिस्सा और मैं जो कुछ भी कर रहा था उसका हिस्सा इस्तेमाल कर रहा था। तुम्हारी मदद के लिए शुक्रिया। – Ryan

+0

आह, ठीक है, क्षमा करें अगर मैं अस्पष्ट था। उन स्प्लेटेड मार्ग मुश्किल हो सकते हैं। – PreciousBodilyFluids

2

रयान बेट्स Railscasts #154 में बहुरूपी संघों कवर, लेकिन उदाहरण के रेल 2 और सक्रिय रिकॉर्ड किया गया था। मैंने कुछ बदलाव करके रेल 3 और मोंगोइड का उपयोग करके अपना उदाहरण काम करने में कामयाब रहे।

पोस्ट और पिक्चर मॉडल में, निम्न पंक्ति जोड़ें:

embeds_many :comments, :as => :commentable 

Mongoid associations documentation के अनुसार, सभी embedded_in संघों बहुरूपी होते हैं। Mongoid का उपयोग करते समय आपको रेलवेकास्ट में उल्लिखित commentable_id और commentable_type कॉलम की आवश्यकता नहीं है, क्योंकि टिप्पणी टिप्पणी के बच्चे हैं।

embedded_in :commentable, :inverse_of => :comment 

सेटअप इस तरह config/routes.rb में मार्गों:

resources posts do 
    resources comments 
end 

resources pictures do 
    resources comments 
end 

एक private पद्धति के रूप में अपनी टिप्पणी नियंत्रक के लिए निम्न विधि जोड़ें टिप्पणी मॉडल में, निम्न पंक्ति जोड़ें। यह रयान की विधि के समान है:

def find_commentable 
    params.each do |name, value| 
    if name =~ /(.+)_id$/ 
     return $1.classify.constantize.find(value) 
    end 
    end 
    nil 
end 

अपनी टिप्पणी नियंत्रक क्रियाएँ जहां टिप्पणी खोजने की जरूरत से प्रत्येक में, पहले फोन find_commentable विधि माता-पिता के लिए। एक बार माता-पिता मिलने के बाद, आप टिप्पणी योग्य टिप्पणियों के माध्यम से आईडी द्वारा टिप्पणी प्राप्त कर सकते हैं। उदाहरण के लिए, संपादित करें कार्रवाई में कोड टिप्पणी खोजने के लिए इस तरह दिखेगा:

@commentable = find_commentable 
@comment = @commentable.comments.find(params[:id]) 

हर क्रिया के शुरू में find_commentable बुलाने की पुनरावृत्ति को कम करने के लिए, आप के शीर्ष पर फिल्टर से पहले एक डाल सकता है इस तरह नियंत्रक:

class CommentsController < ApplicationController 
    before_filter :find_commentable 
    ... 

और फिर करने के लिए find_commentable विधि में वापसी कॉल बदलने के लिए:

return @commentable = $1.classify.constantize.find(value) 

मैं इस मुलाकात का उपयोग कर किसी भी समस्याओं का सामना करना पड़ा नहीं किया है होड, लेकिन अगर आप किसी भी मुद्दे पर आते हैं तो कृपया उन्हें इंगित करें।

0

अप्राकृतिक के उत्तर पर चित्रण, मुझे काम करने के संबंध मिलते हैं लेकिन नामित मार्ग अभी भी नहीं किए गए हैं।

मैं अभी भी रेल 3 पर बहुत नया हूं लेकिन मुझे eval का उपयोग करके एक सरल समाधान मिला।

उदाहरण के लिए, मेरी परियोजना में, पॉलिमॉर्फिक माता-पिता (मेरे ऐप में मोंगोइड ऑब्जेक्ट्स उत्पाद और श्रेणी के रूप में प्रतिनिधित्व किए गए) को find_comentable के संशोधन का उपयोग करके @imagable के रूप में परिभाषित किया गया है और संपादित किए जाने वाले बच्चे को @image के रूप में जाना जाता है।

send("#{@imagable.class.name.downcase}_image_url", @imagable, image) 

यह सब नामित पथ के लिए काम करता है:

एक यूआरएल ऐसे product_image_path(@imagable, @image) जो करता है GET => products/:product_id/images/ साथ प्रतिस्थापित किया जा सकता है। उदाहरण के लिए:

link_to 'Edit', send("edit_#{@imagable.class.name.downcase}_image_path", @imagable, image) 
link_to 'Destroy', send("#{@imagable.class.name.downcase}_image_url", @imagable, image), :confirm => 'Are you sure?', :method => :delete 

नकारात्मक पक्ष यह करने के लिए यह सब अपने विचारों पर और नियंत्रकों भी आप में रीडायरेक्ट में भेजता छोड़ देता है।

क्या मार्गों के माध्यम से ऐसा करने के लिए एक और अधिक शानदार समाधान है?

* प्रतिस्थापित eval साथ भेज

+0

आप [पॉलिमॉर्फिक रूट्स] का उपयोग कर सकते हैं (http://api.rubyonrails.org/classes/ActionDispatch/Routing/PolymorphicRoutes.html), उदा। 'edit_polymorphic_path (छवि योग्य, छवि)' –

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