2012-11-17 12 views
14

मैंने ऐसी परिस्थिति पर ठोकर खाई है जहां मेरा एप्लिकेशन किसी आईडी की तलाश करता है जो डेटाबेस में मौजूद नहीं है। एक अपवाद फेंक दिया जाता है। बेशक, यह किसी भी वेब डेवलपर के लिए एक सुंदर मानक स्थिति है।आईडी नहीं मिलने पर सामान्य नियंत्रक में सामान्य बचाव - RoR

this answer के लिए धन्यवाद मुझे पता है कि इस स्थिति से बचाव सौदों का उपयोग कर बहुत बड़े करीने से, इसलिए जैसे:

def show 
    @customer = Customer.find(params[:id]) 
    rescue ActiveRecord::RecordNotFound #customer with that id cannot be found 
    redirect_to action: :index  #redirect to index page takes place instead of crashing 
end 

मामले में ग्राहक नहीं पाया जा सकता है, उपयोगकर्ता सूचकांक पृष्ठ पर पुनः निर्देशित किया जाता है। यह बिल्कुल ठीक काम करता है।

अब, यह सब अच्छा है, लेकिन मुझे शो, संपादित, नष्ट, इत्यादि जैसे प्रत्येक नियंत्रक विधि के लिए एक ही विशिष्ट प्रयास की आवश्यकता है, जो एक विशिष्ट आईडी की आवश्यकता है। या वहाँ किसी भी तरह से आम तौर पर मेरी नियंत्रक बताने के लिए है कि अगर वह अपने तरीकों में से किसी में आईडी नहीं मिल रहा है, यह सूचकांक पृष्ठ पर रीडायरेक्ट करेगा नहीं है (:

कहा करने के बाद कि, यहाँ मेरे सवाल है , आमतौर पर, एक विशिष्ट कार्य करते हैं)?

उत्तर

31

आप इस कार्य के लिए rescue_from उपयोग करना चाहिए। Action Controller Overview Guide

class ApplicationController < ActionController::Base 
    rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found 

    private 

    def record_not_found 
    redirect_to action: :index 
    end 
end 
+1

बहुत बढ़िया, यह चाल है, धन्यवाद! जिज्ञासा से बाहर: यह विधि निजी क्यों होनी चाहिए? – weltschmerz

+1

बस सफाई के लिए: विधि को अन्य नियंत्रकों के लिए दृश्यमान होने की आवश्यकता नहीं है, यही कारण है कि इसे निजी घोषित किया जाता है। यदि विधि निजी घोषित नहीं की जाती है तो यह समान रूप से काम करेगी। – Baldrick

+2

आप एक फ्लैश संदेश भी जोड़ सकते हैं फ़्लैश [: नोटिस] = "कोई रिकॉर्ड नहीं मिला" –

8

रेल एक अंतर्निहित rescue_from वर्ग विधि:

class CustomersController < ApplicationController 
    rescue_from ActiveRecord::RecordNotFound, with: :index 
    ... 
end 
+0

यह बहुत सुंदर लग रहा है। मैंने कोशिश की, लेकिन यह मुझे ब्राउज़र में एक खाली पृष्ठ के साथ छोड़ देता है, और यूआरएल में यह अभी भी 'ग्राहक/आईडी' कहता है। क्या मैं कुछ भूल रहा हूँ? ऐसा लगता है कि यह इसे पुनर्निर्देशित करने के बजाय इंडेक्स प्रस्तुत करने का प्रयास करता है। – weltschmerz

+0

आप सही हैं .. बाल्ड्रिक नीचे बताए गए कुछ की कोशिश करें (यानी, एक रीडायरेक्ट के साथ एक मध्यवर्ती विधि)। –

1

कुछ मामलों में में उदाहरण देखें, मैं सुझाव है कि आप Model.find_by_id(id) का उपयोग के रूप में Model.find(id) करने का विरोध किया। अपवाद फेंकने के बजाय, .find_by_idnil देता है। अगर रिकॉर्ड नहीं मिला।

बस NoMethodError से बचने के लिए निल्स की जांच करना सुनिश्चित करें!

पीएस इसके लायक होने के लिए, Model.find_by_id(id) कार्यात्मक रूप से Model.where(id: id) के बराबर है, जो आपको इच्छित कुछ अतिरिक्त संबंध बनाने की अनुमति देगा।

3

आप एक ही नियंत्रक के भीतर यह कर (के रूप में हर नियंत्रक में विश्व स्तर पर ऐसा करने के खिलाफ) के बारे में बात कर रहे हैं तो यहाँ एक जोड़े विकल्प हैं:

आप अपने संसाधन सेटअप करने के लिए एक before_filter का उपयोग कर सकते हैं:

class CustomerController < ApplicationController 
    before_filter :get_customer, :only => [ :show, :update, :delete ] 

    def show 
    end 

    private 

    def get_customer 
    @customer = ActiveRecord.find(params[:id]) 
    rescue ActiveRecord::RecordNotFound 
     redirect_to :action => :index 
    end 
end 

या आप इसके बजाय एक विधि का उपयोग कर सकते हैं। मैं बजाय इस दिशा में आगे बढ़ गया है विचारों के अंदर उदाहरण चर का उपयोग कर, और यह भी आप अपनी समस्या को हल करने में मदद मिलेगी:

class CustomerController < ApplicationController 
    def show 
    # Uses customer instead of @customer 
    end 

    private 

    def customer 
    @customer ||= Customer.find(params[:id]) 
    rescue ActiveRecord::RecordNotFound 
     redirect_to :action => :index 
    end 
    helper_method :customer 
end 
+0

शब्द "वैश्विक रूप से" मेरा ध्यान पकड़ा। क्या यह सभी नियंत्रकों में ऐसा करने का कोई तरीका है? यह बेहद सहायक होगा। – weltschmerz

+1

मुझे लगता है कि जो मैंने वैश्विक तरीके से वर्णित किया है, उसे थोड़ा मेटाप्रोग्रामिंग की आवश्यकता हो सकती है। लेकिन सक्रिय रूप से ActiveRecord :: RecordNotFound को विश्व स्तर पर सहेजने के लिए आप अपने एप्लिकेशन नियंत्रक में rescue_from का उपयोग कर सकते हैं। – bratsche

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