Reputation: 21
I'm learning how to build a Rails gem (engine, to be more specific). I first read some existing open source code like Devise, but I can't understand the controllers inside it. In app/controllers
there is _devise_controller.rb_ with module hierarchy
class DeviseController < Devise.parent_controller.constantize
but in lib/devise/controllers/
there are also many controllers with module hierarchy
module Devise
module Controllers
what's the difference between these controllers (like which is called when I get "users/sign_up")? Can someone who has more experience using Devise explain?
Upvotes: 2
Views: 237
Reputation: 76784
I've included controllers in a gem I wrote some time back.
One of the main reasons for using the namespace is because your entire gem should be under the duress of a single module:
#lib/exception_handler.rb
module ExceptionHandler
#Exception Handler
class Exceptions < Rails::Engine
This means that if you're calling a controller from within the gem (which is meant to be self-contained), you'll generally have to invoke it inside the module:
ExceptionHandler::ExceptionController.action(:show).call(env) }
--
In the sense of Devise, it makes sense for them to include their controllers in a namespace for two reasons:
which is called when I get "users/sign_up"
The devise controllers can be broken down by the routes Devise sets:
new_user_session GET /users/sign_in {controller:"devise/sessions", action:"new"}
user_session POST /users/sign_in {controller:"devise/sessions", action:"create"}
destroy_user_session DELETE /users/sign_out {controller:"devise/sessions", action:"destroy"}
These are just routes for the sessions
controller (which handles login etc).
There are other routes including registrations
etc.
The key here is to understand that Devise has to work "out of the box" -- otherwise most people wouldn't use it. It achieves this by self-containing its controllers, ensuring that, as sanfor
recommended, they are not conflicted.
If you have more specific requests, I'll gladly answer them for you.
Upvotes: 1
Reputation: 7405
I assume that the Devise controllers are inside their own module to not pollute the global namespace. Check for example the case in this answer where the new class is based on Devise's RegistrationController
class RegistrationsController < Devise::RegistrationsController
if it weren't inside the Devise the name RegistrationsController would already be taken.
The controllers under app/controllers/devise
are the actual controllers that the router redirects requests to. The ones under lib/devise/controllers
are helpers for the controllers and thus are in module Devise::Controllers for convenience.
When users/sign_up
is called, it is routed to _registrations_controller.rb:6_. This isn't done the normal way via routes.rb probably because Devise needs to adjust the URLs per application since you don't always use users as the path. Instead is done by devise/rails/routes.rb
which is where the line
mount_devise_token_auth_for 'User', at: 'auth'
from actual applications routes.rb takes to.
Upvotes: 1