46

Are controllers in devise automatically generated? How do you access them?

I know for views you do rails generate devise_views.

mabu
  • 286
  • 8
  • 26
katie
  • 2,921
  • 8
  • 34
  • 51
  • 2
    Repost of this question here: http://stackoverflow.com/questions/3546289/override-devise-registrations-controller – Devin M Jun 04 '11 at 01:38
  • The answer to this question depends on which version of Rails you are using. If using Rails 4 in 2016, then the correct answer is not marked correct. – Daniel Viglione Jun 21 '16 at 22:36

5 Answers5

58

Under the assumption that you want to see these controllers in order to modify or override them, Devise now provides a simple generator which recreates their controllers in your app to make this easy. As per the documentation (which will be most up-to-date):

1) Create your custom controllers using the generator which requires a scope:

console

rails generate devise:controllers [scope]

If you specify users as the scope, controllers will be created in app/controllers/users/. And the sessions controller will look like this:

class Users::SessionsController < Devise::SessionsController
  # GET /resource/sign_in
  # def new
  #   super
  # end
  ...
end

2) Tell the router to use this controller:

devise_for :users, controllers: { sessions: "users/sessions" }

3) Copy the views from devise/sessions to users/sessions. Since the controller was changed, it won't use the default views located in devise/sessions.


4) Finally, change or extend the desired controller actions.

You can completely override a controller action:

class Users::SessionsController < Devise::SessionsController
  def create
    # custom sign-in code
  end
end

Or you can simply add new behaviour to it:

class Users::SessionsController < Devise::SessionsController
  def create
    super do |resource|
      BackgroundWorker.trigger(resource)
    end
  end
end

This is useful for triggering background jobs or logging events during certain actions.

Remember that Devise uses flash messages to let users know if sign in was successful or unsuccessful. Devise expects your application to call flash[:notice] and flash[:alert] as appropriate. Do not print the entire flash hash, print only specific keys. In some circumstances, Devise adds a :timedout key to the flash hash, which is not meant for display. Remove this key from the hash if you intend to print the entire hash.

Sharvy Ahmed
  • 7,247
  • 1
  • 33
  • 46
Erik Trautman
  • 5,883
  • 2
  • 27
  • 35
  • This is the best way to do it now and should be the top answer. – Joe Edgar Aug 30 '15 at 19:22
  • I didn't have to change the location of my views, I'm assuming rails is just looking for them in the Devise directory because it be smart, yo. – LpLrich Nov 19 '15 at 14:25
  • Yes, I agree that this should now be marked as the correct answer in 2016. – Daniel Viglione Jun 21 '16 at 22:35
  • Also run bundle update devise to make sure your version supports it. Also You do not need to change location of views. – Daniel Viglione Jun 21 '16 at 23:21
  • This is still only going to show a controller where the methods just contain `super`... It helps with overriding but you still have to copy code from the original controller if you don't want to rewrite all of it. Is there an option to actually show the whole controller? In my example I just want to do a check for the environment mode and if it's in development skip the confirmation mail. ps: found awesome answer here: http://stackoverflow.com/a/21169179/5909738 – Tashows Aug 16 '16 at 19:46
  • here is where you do the `show` , `edit` and `update`? – Steven Aguilar Jun 16 '19 at 20:18
40

Devise uses internal controllers, which you can access and subclass in your own code. They are under the Devise module. For example, to extend the RegistrationsController:

class MembershipsController < Devise::RegistrationsController
  # ...
end

Then all you have to do is configure Devise's routes to use your controller instead:

devise_for :members, :controllers => { :registrations => 'memberships' }
Matheus Moreira
  • 17,106
  • 3
  • 68
  • 107
  • 10
    Is there a way to simply view the devise controllers like you would with the views? In my case, I would like to add code to the devise registrations controller instead of re-writing it; and I'm not sure where and how I want to add to it without seeing what is in their first. Any suggestions? – vich Aug 25 '11 at 19:06
  • 7
    @mmichael, you can find the source code of Devise's controllers [here](https://github.com/plataformatec/devise/tree/master/app/controllers/devise). By reading the source you can understand what each method is doing, and then figure out the best way to implement your features. – Matheus Moreira Aug 29 '11 at 00:37
  • 2
    Thanks, finally some clarity on the matter! – mjgpy3 Feb 24 '13 at 06:54
11

$ rails generate devise:controllers SCOPE [options]

Options: -c, [--controllers=one two three]

Select specific controllers to generate (confirmations, passwords, registrations, sessions, unlocks, omniauth_callbacks)

Use -c to specify which controller you want to overwrite. If you do not specify a controller, all devise controllers will be created. For example:

rails generate devise:controllers users -c=sessions

This will create a controller class at app/controllers/users/sessions_controller.rb like this:

 class Users::ConfirmationsController < Devise::ConfirmationsController
    content...
 end
Nimish
  • 1,053
  • 13
  • 29
10

Below one is for Rails 5

Generate rails devise controllers using the following command:

rails generate devise:controllers users

if you modified the above generated controllers, add the following line to the routes.rb,

devise_for :users, controllers: {registrations:'user/registrations'}

Your modifications will take effect once you restart the rails server

Sujeev
  • 276
  • 4
  • 10
  • You will also need to move views from `app/views/devise/CONTROLLER/...` -> `app/views/users/CONTROLLER/...` when you do this so that your new controller can find them. – antun Jun 20 '20 at 23:26
1

To define custom controller behavior,

see @ErikTrautman's answer.

But if you're trying to understand what Devise is doing under the hood,

you must inspect the source (specifically, in the project root's app/ directory). @MatheusMoreira provides a link to the source on GitHub, but if you'd rather browse it locally in your own text editor, you can find the install location of the Devise gem with gem which devise.

For instance, to see Devise::SessionsController:

$ vim $(gem which devise | sed 's|\(.*\)\(/.*\)\{2\}|\1|')/app/controllers/devise/sessions_controller.rb

(Or, you could just clone the git repo and poke around that way.)

$ git clone https://github.com/plataformatec/devise
$ cd devise
$ vim app/controllers/devise/sessions_controller.rb
Ryan Lue
  • 916
  • 10
  • 29