devise: Devise is ApplicationController-centric to a fault
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:
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:
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.
About this issue
- Original URL
- State: closed
- Created 13 years ago
- Comments: 19 (10 by maintainers)
Ok. So recap:
This is fixed on master. One can set Devise.parent_controller = “Engine::ApplicationController”. I recommend doing just after require “devise” in your engine.
Will be addressed with a patch similar to what you said above
The root_path won’t be fixed. I believe it should point to the application
root_path
always. The maximum we can do is to check if it is defined and return “/” if not.The namespace issue happens in a namespaced engine, rails forces the router to be by default
scope :module => EngineName
. I can add :module => false to Devise as a way to override the current scope configuration.Sounds good?