9

I have a Rails 3.2 application that uses Apartment, which is used as a middleware. Apartment throws an Apartment::SchemaNotFound exception and there is no way to rescue it with rescue_from from the ApplicationController. I thought I'd use config.exceptions_app as described in point #3 in this blog post, but I can't set the router as the exception app, I assume I have to create my own.

So the question is: How do I proceed?

Jenn
  • 3,143
  • 1
  • 24
  • 28
Robert Audi
  • 8,019
  • 9
  • 45
  • 67

2 Answers2

4

I had a similar problem with another piece of middleware throwing a custom exception, so I haven't actually looked at Apartment at all, but maybe something like this:

#app/middleware/apartment/rescued_apartment_middleware.rb
module Apartment
  class RescuedApartmentMiddleware < Apartment::Middleware
    def call(env)
      begin
        super
      rescue Apartment::SchemaNotFound
        env[:apartment_schema_not_found] = true # to be later referenced in your ApplicationController
        @app.call(env) # the middleware call method should return this, but it was probably short-circuited by the raise
      end
    end
  end
end

Then in your environment:

config.middleware.use(Apartment::RescuedApartmentMiddleware, etc)

To access the env variable you set from ApplicationController or any controller:

if request.env[:apartment_schema_not_found]
  #handle
end

Combo of How to rescue from a OAuth::Unauthorized exception in a Ruby on Rails application? and How do I access the Rack environment from within Rails?

tfwright
  • 2,844
  • 21
  • 37
Jenn
  • 3,143
  • 1
  • 24
  • 28
4

We've purposefully left Apartment pretty minimal to allow you the handle the exception itself without really needing any Rails specific setup.

I'd do something similar to what @jenn is doing above, but I wouldn't bother setting a rack env and dealing with it later, just handle the response completely in rack.

It's typical for instance that you maybe just want to redirect back to / on SchemaNotFound

You could do something like

module MyApp
  class Apartment < ::Apartment::Elevators::Subdomain
    def call(env)
      super
    rescue ::Apartment::TenantNotFound
      [302, {'Location' => '/'}, []]
    end
  end
end

This is a pretty raw handling of the exception. If you need something to happen more on the Rails side, then @jenn's answer should also work.

Check out the Rack for more details

brad
  • 31,987
  • 28
  • 102
  • 155
  • 1
    FYI trying to redirect to '/' will cause an infinite redirect, we need to parse out the root_url, doing this in rack is a bit nasty so bubbling up to ActionController is probably a good idea. – Jurre Jan 02 '15 at 10:43