2012-11-17 13 views
14

Uygulamamın veritabanında bulunmayan bir kimliği aradığı bir duruma rastladım. Bir istisna atılır. Tabii ki, bu herhangi bir web geliştiricisi için oldukça standart bir durumdur. Müşteri bulunamayan durumdaKimlik bulunamadığı zaman denetleyici genelinde genel kurtarma - RoR

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 

, kullanıcı dizin sayfasına yönlendirildi: this answer için

Teşekkür Öyle gibi oldukça düzgün durumla kurtarma fırsatları kullanarak biliyoruz. Bu kesinlikle iyi çalışıyor.

Şimdi, bu her şey güzel, ancak gösterme, düzenleme, imha etme, vb. Gibi eylemlerde aynı kurtarma girişimlerini, yani her bir özel gereksinime ihtiyacı olan her her denetleyici yöntemini kullanmam gerekiyor. orada onun yöntemlerin herhangi birinde kimliği bulamazsa, bu indeks sayfasına yönlendirme edeceğini genellikle benim denetleyicisi anlatmak için herhangi bir yolu değil midir (veya:

işte sorum, söyledikten , genellikle, belirli bir görevi gerçekleştirmek)?

cevap

31

. Belli durumlarda 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

Başar, bu hile yapar, teşekkür ederim! Merak etme: Neden bu yöntem özel olmalı? – weltschmerz

+1

Sadece temizlik için: yöntemin diğer denetleyicilere görünür olması gerekmez, bu nedenle özel olarak bildirilir. Yöntem özel olarak bildirilmemişse eşit olarak çalışır. – Baldrick

+2

Ayrıca flash mesajı flaş ekleyebilirsiniz [: haber] = "Kayıt bulunamadı" –

8

Raylar yerleşik bir rescue_from sınıf yöntemi: Bu görev için rescue_from kullanmalıdır

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

Bu çok zarif görünüyor. Denedim, ancak tarayıcıda boş bir sayfa ile beni bırakır ve url hala "müşteriler /: id" diyor. Bir şey mi eksik? Görünüşe göre bana yönlendirme yapmak yerine dizin oluşturmaya çalışıyor. – weltschmerz

+0

Haklısınız .. Baldrick'in aşağıda önerdiği gibi bir şey deneyin (yani, bir yönlendirme ile ara bir yöntem). –

1

örneğe bakın, ben Model.find(id) ile değil de Model.find_by_id(id) kullanmanızı öneriyoruz. Bir istisna atmak yerine, .find_by_id, nil değerini döndürür. kayıt bulunamadıysa.

NoMethodError'dan kaçınmak için nils'i kontrol ettiğinizden emin olun!

P.S. Değeri için, Model.find_by_id(id) işlevsel olarak Model.where(id: id)'a eşdeğerdir, bu da isterseniz bazı ek ilişkiler kurmanızı sağlar. Eğer (her denetleyicisi küresel bunu yerine) tek denetleyici içinde bunu bahsediyorsan

3

sonra burada bir kaç seçenek vardır:

Sen kurulum kaynağına before_filter kullanabilirsiniz:

Veya bunun yerine bir yöntem kullanabilirsiniz. Görünümler içinde örnek değişkenleri kullanmak yerine bu yönde hareket ediyorum ve aynı zamanda sorununuzu çözmenize de yardımcı olur:

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

yardımcı olur. Tüm kontrolörler boyunca bunu yapmanın bir yolu var mı? Bu son derece yararlı olur. – weltschmerz

+1

Küresel bir şekilde tarif ettiğim şeyi yapmak biraz meta programlamayı gerektirebilir. Ama sadece ActiveRecord :: RecordNotFound'u kurtarmak için, ApplicationController'da rescue_from'u kullanabilirsiniz. – bratsche