48

Using Devise to manage users sessions / registrations I would need to perform specific tasks (updating some fields in the users table for this specific user for example) each time a user signs in, and before he gets redirected by devise to the home page for connected users.

Do I have to override devise SessionsController, and if yes, how?

MisterCal
  • 622
  • 2
  • 7
  • 22
Patrice Navarre
  • 555
  • 1
  • 5
  • 8

4 Answers4

72

Alternatively, you can create your own sessions controller

class SessionsController < Devise::SessionsController
  def new
    super
  end

  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message(:notice, :signed_in) if is_navigational_format?
    sign_in(resource_name, resource)
    if !session[:return_to].blank?
      redirect_to session[:return_to]
      session[:return_to] = nil
    else
      respond_with resource, :location => after_sign_in_path_for(resource)
    end
  end
end

And in routes.rb add:

devise_for :users, controllers: {sessions: "sessions"}
Sam Starling
  • 5,298
  • 3
  • 35
  • 52
Pykih
  • 2,769
  • 3
  • 29
  • 38
  • Thanks ! I ended up using the first solution, but will keep this in mind for other similar use cases – Patrice Navarre Dec 14 '12 at 07:20
  • 3
    The code seams to have changed a bit, link to master copy: https://github.com/plataformatec/devise/blob/master/app/controllers/devise/sessions_controller.rb – Daniel Jul 19 '13 at 16:56
28

If you look at Devise's implementation of sessions_controller#create, you'll notice that they yield if you pass a block.

So, just subclass their sessions controllers and pass a block when you call super. To do that, first tell Devise in routes.rb that you'd like to use your own sessions controller:

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

And then create a SessionsController class and pass a block when you call super in your create method. It would look something like this:

# app/controllers/users/sessions_controller.rb

class Users::SessionsController < Devise::SessionsController
  layout "application"
  
  # POST /login
  def create
    super do |user|
      if user.persisted?
        user.update(foo: :bar)
      end
    end
  end
end

Most of the Devise controller methods accept a block, so you could do this for registration, forgot password, etc as well.

notapatch
  • 6,569
  • 6
  • 41
  • 45
stephen.hanson
  • 9,014
  • 2
  • 47
  • 53
20

Devise provides after_database_authentication callback method.You have full access for the current authenticated user object over there.

If you want to update current user name after every successful login you can do that like below.

class User < ActiveRecord::Base
  devise :database_authenticatable

  def after_database_authentication
    self.update_attributes(:name => "your name goes here")
  end 
end
Kick Buttowski
  • 6,709
  • 13
  • 37
  • 58
Soundar Rathinasamy
  • 6,658
  • 6
  • 29
  • 47
  • Don't copy and paste that example because soundar wrote a second "def" where he should have written "end" – heavysixer Apr 13 '13 at 20:24
  • Guys this works fine on Login, but doesn't work when the user sign up (register) for the first time. I am confused, because devise also automatically logs the user in, so it should work. Right? – pastullo Nov 10 '13 at 01:08
0
  • configure devise for using your controller changing config/routes.rb devise_for :users, controllers: { ... , sessions: "sessions", ... }
  • create a app/controllers/sessions_controller.rb or generate it using rails g devise:controllers users -c=sessions

prepend_before_action

class SessionsController < Devise::SessionsController
  prepend_before_action :your_task, only: [:create] # Change this to be any actions you want to protect.

  private

  def your_task
    return if your_task_is_OK # if your task is good, return to the super method otherwise render the new

    self.resource = resource_class.new sign_in_params

    respond_with_navigational(resource) do
      flash.now[:alert] = "your notice message"
      render :new
    end
  end 
end
Feuda
  • 2,335
  • 30
  • 28