2013-08-21 30 views
15

Ruby 2.0 ve Rails 4.0'ı kullanarak Ruby on Rails api yapıyorum. Uygulamam neredeyse sadece bir JSON API'sıdır, dolayısıyla bir hata oluşursa (500, 404), bu hatayı yakalamak ve güzel biçimlendirilmiş bir JSON hata iletisini döndürmek istiyorum.Özel Hatalar Raylarla Çalışma 4.0

Ben de this denedim ve:

rescue_from ActionController::RoutingError, :with => :error_render_method 

def error_render_method 
    puts "HANDLING ERROR" 
    render :json => { :errors => "Method not found." }, :status => :not_found 
    true 
end 

benim ApplicationController olarak.

Bunların hiçbiri hile yapmaz (istisnalar hiç çekilmez). Googling'im bunun 3.1, 3.2 arasında çok değiştiğini gösteriyor ve Rails 4.0'da bunun nasıl yapılacağına dair iyi bir doküman bulamıyorum.

Herkes biliyor mu?

Started GET "/testing" for 127.0.0.1 at 2013-08-21 09:50:42 -0400 

ActionController::RoutingError (No route matches [GET] "/testing"): 
actionpack (4.0.0) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call' 
actionpack (4.0.0) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call' 
railties (4.0.0) lib/rails/rack/logger.rb:38:in `call_app' 
railties (4.0.0) lib/rails/rack/logger.rb:21:in `block in call' 
activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `block in tagged' 
activesupport (4.0.0) lib/active_support/tagged_logging.rb:25:in `tagged' 
activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `tagged' 
railties (4.0.0) lib/rails/rack/logger.rb:21:in `call' 
actionpack (4.0.0) lib/action_dispatch/middleware/request_id.rb:21:in `call' 
rack (1.5.2) lib/rack/methodoverride.rb:21:in `call' 
rack (1.5.2) lib/rack/runtime.rb:17:in `call' 
activesupport (4.0.0) lib/active_support/cache/strategy/local_cache.rb:83:in `call' 
rack (1.5.2) lib/rack/lock.rb:17:in `call' 
actionpack (4.0.0) lib/action_dispatch/middleware/static.rb:64:in `call' 
railties (4.0.0) lib/rails/engine.rb:511:in `call' 
railties (4.0.0) lib/rails/application.rb:97:in `call' 
rack (1.5.2) lib/rack/lock.rb:17:in `call' 
rack (1.5.2) lib/rack/content_length.rb:14:in `call' 
rack (1.5.2) lib/rack/handler/webrick.rb:60:in `service' 
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/httpserver.rb:138:in `service' 
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/httpserver.rb:94:in `run' 
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/webrick/server.rb:295:in `block in start_thread' 


Rendered /Library/Ruby/Gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.0ms) 
Rendered /Library/Ruby/Gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/routes/_route.html.erb (2.9ms) 
Rendered /Library/Ruby/Gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/routes/_route.html.erb (0.9ms) 
Rendered /Library/Ruby/Gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/routes/_table.html.erb (1.1ms) 
Rendered /Library/Ruby/Gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (38.3ms) 

Ben hiç bu kadar şey yakalamak gerektiğini almak ve uygun json dönmek istiyorum sanmıyorum: bir 404 sayfasına gittiğinizde

Düzenleme İşte yığın izleme hata yanıtı. Aynı şekilde hataları her türlü cevap istiyorsanız

+0

Hmmmm, bu aslında nasıl kurulduğuna çalışıyor olabilir ... Biraz daha test edeyim. –

cevap

0

bu deneyin

rescue_from StandardError, :with => :error_render_method

siz, geliştirme modunda bu davranışı istemek

altında yukarıdaki kodu eklemezseniz unless Rails.application.config.consider_all_requests_local bu rails4 çalışır

+1

Bilmek güzel, ama bu hatayı yakalamıyor gibi görünüyor (ben bir yığın izi ekledim). Benim "error_render_method" hiç çağrılmıyor. –

+0

Raylarım 3.2.13 kullanıyorum ve benim için çalışıyor. Rayların etrafında bir şey değiştirmiş olabilirler. 4 – usha

+0

Bu, ActionController ürününüze yanlış girdiğinizde birkaç farklı durumda çağrılmaz. Belgelerden: "exception.is_a? (Klass) 'ın gerçek tuttuğu birinci sınıfın işleyicisi, herhangi bir" – WattsInABox

9

doğrudan tüm hataları yönetebilir bu şekilde: bir hata, bir aPI çağrısından oluştuğunda örneğin size json olarak error_info işleyebilen ..

application_controller.rb

class ApplicationController < ActionController::Base 
    protect_from_forgery 


    # CUSTOM EXCEPTION HANDLING 
    rescue_from StandardError do |e| 
    error(e) 
    end 

    def routing_error 
    raise ActionController::RoutingError.new(params[:path]) 
    end 

    protected 

    def error(e) 
    #render :template => "#{Rails::root}/public/404.html" 
    if env["ORIGINAL_FULLPATH"] =~ /^\/api/ 
    error_info = { 
     :error => "internal-server-error", 
     :exception => "#{e.class.name} : #{e.message}", 
    } 
    error_info[:trace] = e.backtrace[0,10] if Rails.env.development? 
    render :json => error_info.to_json, :status => 500 
    else 
     #render :text => "500 Internal Server Error", :status => 500 # You can render your own template here 
     raise e 
    end 
    end 

    # ... 

end 

routes.rb

MyApp::Application.routes.draw do 

    # ... 

    # Any other routes are handled here (as ActionDispatch prevents RoutingError from hitting ApplicationController::rescue_action). 
    match "*path", :to => "application#routing_error", :via => :all 
end 
16

isteği bile uygulamanızı isabet değildir. Raylar değiştirme (üretimde) rotalarınızı

kamu/404.html sayfasını uygulamanıza isteği göndermek yerine (Geliştirilmekte olan) bir hata görüntüler veya hale getirecek böylece

Bir catchall rota tanımlamak gerekir. rb dosya içerecek şekilde

class ErrorsController < ApplicationController 

    def catch_404 
    raise ActionController::RoutingError.new(params[:path]) 
    end 
end 

Ve

match "*path", to: "errors#catch_404", via: :all 

aşağıdaki Ve denetleyicisi senin rescue_from sonra hatayı yakalamak gerekir.

+1

Diğer istek yöntemleri için de olabileceğinden, 'get'i rotalarda' match 'olarak değiştirmek isteyebilirsiniz. – dylanfm

+0

Doğru, düzenlenmiş. Teşekkürler! – silasjmatson

+1

Raylar 4, "eyleminizi hem GET hem de POST olarak gösterme, [by] ekleme: [: get,: post]' "ile hatırlatmanızı hatırlatacaktır - bunu da unutmayın! :) – sameers

14

API 404'lerin işlemek için en basit yolu olarak bu konuda yerleşmek ettik, birkaç varyasyon denedikten sonra:

# Passing request spec 
describe 'making a request to an unrecognised path' do 
    before { host! 'api.example.com' } 
    it 'returns 404' do 
    get '/nowhere' 
    expect(response.status).to eq(404) 
    end 
end 

# routing 
constraints subdomain: 'api' do 
    namespace :api, path: '', defaults: { format: 'json' } do 
    scope module: :v1, constraints: ApiConstraints.new(1) do 
     # ... actual routes omitted ... 
    end 
    match "*path", to: -> (env) { [404, {}, ['{"error": "not_found"}']] }, via: :all 
    end 
end 
+0

+1, rota dosyasında tutmak ve bir test eklemek için. Uygulamamda bu ya da daha az verbatim kullandım, teşekkürler! –

1

ben 404 kullandım.Ortak klasörden html ve bu dev bir ortamda. Ben kod parçalarının aslında o iş yapılmış ne küçük bir deney yaptım Ancak

:
Aslında cevabını aldık. İşte sadece eklediğim kod parçaları.

yapılandırma

class ApplicationController < ActionController::Base 
    def catch_404 
     render :file => 'public/404.html', :status => :not_found 
    end 
end 

orijinalin bazı ihtiyaç vardır neden olarak herhangi bir yorum ve açıklamalar takdir Will/routes.rb

Rails.application.routes.draw do 
    // other routes 
    match "*path", to: "application#catch_404", via: :all 
end 

app/kontrolörleri/application_controller.rb . Örneğin, bu kod

raise ActionController::RoutingError.new(params[:path]) 

bu hattı kullanarak ve bu

rescue_from ActionController::RoutingError, :with => :error_render_method 

rescue_from ve raise ActionController::RoutingError Çünkü eski Raylar sürümlerinden popüler cevap gibi görünüyor.