Ismail Moghul
Ismail Moghul

Reputation: 2984

Sinatra - Error Handling

I'm trying to make my sinatra app show a custom error page when an error is raised on the server (e.g. an IOError or ArgumentError).

Currently I'm using AJAX to load the results into a certain #results div, but if and when an error arises on the server, I would like an error page to open up on a new page.

Currently, the IOError is shown on the server and a error is seen in the console (the server responded with a status of 500 (Internal Server Error)). Other than that, nothing happens.

I think that I have to play about with the Javascript (as well as the Sinatra::Base class) but I've spent the whole of yesterday and this morning not getting anywhere.

I would be very grateful for any help. I've created an oversimplified version of my app which I have shown below...

Sinatra_app.rb

require 'sinatra/base'
require9 'sinatra'
require 'slim'

# A helper module
module GVhelpers
  def create_results(name)
    # raise IOError, "There's a problem..."
    return "<p>The Server Says 'Hey #{name}'</p>"
  end
end

class GVapp < Sinatra::Base
  helpers GVhelpers
  set :root, File.dirname(__FILE__)

  error do 
    @error = env['sinatra.error']
    slim :"500", :locals => {:error => error}
  end

  get '/' do
    slim :index
  end

  post '/form' do
    name = params[:personName]
    create_results(name)
  end
end

GVapp.run!

index.slim (in views folder)

script src="/jquery.min.js"
script src="/Gvapp.js"

form#sayHey action="/form" method="post"
  |  Name: 
  input type="text" name="personName"
  br
  input type="submit"
#output

500.slim (in views folder)

h1  Oops! Something went Wonky!
p  Apologies, there was an error with your request:
    strong  request.env['sinatra.error'].message
p  If the error persists, please contact the administrator.

Gvapp.js (in public folder)

$(document).ready(function() {

  $('#sayHey').submit(function(e) {

    e.preventDefault();

    $.ajax({
      type: 'POST',
      url: '/form',
      data: $('#sayHey').serialize(),
      success: function(response){
        $('#output').html(response);
      }
    })

  })
})

Upvotes: 3

Views: 5254

Answers (1)

user4111192
user4111192

Reputation:

Sinatra swallows exceptions when run in the development environment by default and shows its debugging error page instead. So, to trigger your custom error handlers, you have to either run the application inside a Rack environment other than development (probably production), or preferably, tell Sinatra to not use its default error handlers in development mode.

Consider the following, standalone Sinatra application example:

require "sinatra"

#disable :show_exceptions

get "/" do
  raise RuntimeError.new("boom")
end

error RuntimeError do
  "A RuntimeError occured"
end

If you run this application using the default development environment like this:

$ ruby foo.rb

Then you will get Sinatra’s default error page. If you uncomment the disable line in the example, the error handler will be triggered instead, displaying a page containing "A RuntimeError occured". Alternatively, you can, as explained, run the application in an environment other than development as only that one pre-sets the show_exception setting. You can do that by setting the RACK_ENV environment variable:

$ RACK_ENV=production ruby foo.rb

For development purposes, setting RACK_ENV to production is not the correct way of course. Use disable :show_exceptions instead. You can use a configure block as outlined in the Sinatra README to conditionally disable the setting for the development environment.

configure :development do
  disable :show_exceptions
end

That behaviour is documented in Sinatra’s documentation on configuration, along with several other useful settings.

Upvotes: 9

Related Questions