plataformatec/devise — Issue #1539: Devise is ApplicationController-centric to a fault
Author: BrucePerens
Created: 2012-01-01 06:36:24+00:00
State: open

It used to be that Rails programmers wrote their application as a single Rails program. These days, many of us are writing our applications as collections of multiple engines, with nothing in the central application except what is necessary to load those engines and mount their routes. Devise fails that sort of application in multiple ways. So many ways that it's probably time for the Devise documentation to bear a warning that it doesn't work at present to use Devise from engines.

Devise internals depend on `ApplicationController`, and Devise installs its methods and helpers in `ApplicationController`. Engine-centric applications are unlikely to contain an `ApplicationController`.

Instead of installing them in `ApplicationController`, use something like this to install Devise methods and helpers. This installs in both `ActionController::Base` *and* its descendants, as there will be some descendants that have been initialized before Devise:

```ruby
ActionController::Base.class_eval do
# Install methods and helpers here.
end
ActionController::Base.descendants.each do |klass|
klass.class_eval do
# Install methods and helpers here.
end
end
'''

Devise expects its named routes to live in `main_app`. The only way to tell Devise that the named routes are in an engine's route table is to re-write all of its views by hand.

Devise expects a root URL handler in `main_app` rather than an engine, and can't fall back if there isn't one. Here's one way to fall back:

```ruby
main_app.respond_to?(:root_url) ? main_app.root_url : '/'
'''

When used from a namespaced engine, Devise points all of its routes to controllers in the engine rather than Devise. The only way to turn this off seems to be to define *all* of the controllers used by Devise, just defining :module is insufficient, the result doesn't match the internal controller paths in Devise.