Custom Error Handling with Rails 4.0

后端 未结 5 719
我寻月下人不归
我寻月下人不归 2020-12-24 14:49

I\'m building a Ruby on Rails api using Ruby 2.0 and Rails 4.0. My app is almost solely a JSON API, so if an error occurs (500, 404), I want to capture that error and return

相关标签:
5条回答
  • 2020-12-24 15:22

    Try this if you want respond to all types of errors in the same way

    rescue_from StandardError, :with => :error_render_method

    If you don't want this behavior in your development mode, add the above code under

    unless Rails.application.config.consider_all_requests_local

    0 讨论(0)
  • 2020-12-24 15:25

    The request isn't even hitting your app.

    You need to define a catchall route so Rails will send the request to your app rather than display an error (in development) or render the public/404.html page (in production)

    Modify your routes.rb file to include the following

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

    And in your controller

    class ErrorsController < ApplicationController
    
      def catch_404
        raise ActionController::RoutingError.new(params[:path])
      end
    end
    

    And your rescue_from should catch the error then.

    0 讨论(0)
  • 2020-12-24 15:25

    After trying a few variations I've settle on this as the simplest way to handle the API 404s:

    # 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 讨论(0)
  • 2020-12-24 15:30

    this works in rails4, this way you can manage directly all errors: for example you can render error_info as json when an an error occurs from an api call..

    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
    
    0 讨论(0)
  • 2020-12-24 15:31

    I used the 404.html from public folder and this is in dev environment.
    I actually got the answer from:

    • https://stackoverflow.com/posts/20508445/revisions and
    • https://coderwall.com/p/w3ghqq

    However, I did a little experiment on what pieces of code actually made it work. Here's are the pieces of code that I only added.

    config/routes.rb

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

    app/controllers/application_controller.rb

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

    Will appreciate any comments and clarifications as to why some of the original are are needed. For instance, using this line of code

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

    and this

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

    Because rescue_from and raise ActionController::RoutingError seem to be the popular answer from the older Rails versions.

    0 讨论(0)
提交回复
热议问题