svonborries
svonborries

Reputation: 73

Rails 4 Devise, with after_sign_in_path_for(resource) always redirect to Show action of Model

I'm stuck with the method after_sign_in_path_for of devise, this is the thing... I have two Models Users and AdminUsers I'm using the active_admin gem

my routes.rb file, looks like this:

devise_for :admin_users, ActiveAdmin::Devise.config
  ActiveAdmin.routes(self)
scope "(:locale)", locale: /es|en/ do
        devise_for :users, path_names: { sign_in: 'login', sign_out: 'logout', 
                                    password: 'password', confirmation: 'confirmation', unlock: 'unlock', 
                                    registration: 'registration', sign_up: 'sign_up' }
    devise_scope :user do
      get "login", to: "devise/sessions#new"
    end
get 'dashboard/index'
end

OK... in my application_controller.rb, I tryed this codes:

def after_sign_in_path_for(resource)
      case resource
          when AdminUser
            #admin_root_path 
            '/admin/dashboard'
            puts'in admin_root_path'
          when User 
            #dashboard_index_path 
            '/dashboard/index'
            puts'in dashboard_index_path'
        else super
        end
      puts 'resource Of AplicationController: ' + resource.class.to_s

  end

  def after_sign_out_path_for(resource_or_scope)
    root_path
  end

As you can see, i have some puts just to check in my console if my case works... and it does, It actually works, this is my console: I'm trying to login as AdminUser, to the admin_root_path of active_admin

Started POST "/admin/login?locale=es" for ::1 at 2015-04-14 12:46:51 -0400
Processing by ActiveAdmin::Devise::SessionsController#create as HTML
....
....
in admin_root_path
resource of AplicationController: AdminUser
Redirected to http://localhost:3000/admin/users/2?locale=es
Completed 302 Found in 113ms (ActiveRecord: 1.8ms)

As you can see, Devise redirect me to the Show page of the current_admin_user.

And here is the console if I try to log in as a User:

Started POST "/es/users/login" for ::1 at 2015-04-14 12:51:18 -0400
Processing by Devise::SessionsController#create as HTML
...
...
in dashboard_index_path
resource of AplicationController: User
Redirected to http://localhost:3000/es/users/2
Completed 302 Found in 106ms (ActiveRecord: 1.4ms)

In the two scenarios Devise is doing the same... redirecting to the show action of each Model, I already tryed to put this code in a custom registrations_controller.rb and the same... Maybe I'm missing something obvious, I'm not expert in Devise, does anyone has an idea of what I'm doing wrong?

The relevant results of rake routes command

....
....
edit_admin_user_password GET   /admin/password/edit(.:format)                 active_admin/devise/passwords#edit

admin_root GET     /admin(.:format)    admin/dashboard#index
....
....
admin_dashboard GET  /admin/dashboard(.:format)    admin/dashboard#index
....
....
dashboard_index GET    (/:locale)/dashboard/index(.:format)   dashboard#index {:locale=>/es|en/}
root GET    /    visitors#index

Upvotes: 2

Views: 5964

Answers (2)

Alejandro Babio
Alejandro Babio

Reputation: 5229

Please, try this:

def after_sign_in_path_for(resource)
  if resource.class == AdminUser
    admin_root_path 
  elsif resource.class == User
    dashboard_index_path 
  end
end

Two things to take care: I use resourse.class I think this is a typo in the question, and not at the code (because it prints puts). Second, after_sign_in_path must return a url, and the last action on your code is a puts that returns nil.

Also you can try:

def after_sign_in_path_for(resource)
  dashboard_index_path 
end

To see after_sign_in_path_for working for first time. And move forward from this starting point.

If all this doesn't work, please publish sign_in and login routes.

Edit: After reading your post I realize that case doesn't (wrong: it works) work, because case works with === and resource.class === AdminUser always return false (are diferent objects). You must ask for resource.class == AdminUser or resource.is_a?(AdminUser). More of case match here. I also update the after_sign_in_path method.

Edit 2 After reading @CJBrew comment, and these experiments at irb:

(main) > pp = Person.first
=> "#<Person id: 1 ..."
(main) > pp === Person
=> false
(main) > Person === pp
=> true
(main) > case pp
(main) | when Person  
(main) |   'yes'
(main) | end  
=> "yes"

I can say that this code must work fine :

def after_sign_in_path_for(resource)
  case resource
  when User
    root_path
  when AdminUser
    admin_contexts_path
  end
end

Because case use === with the when value as object and the case value as param. In this case the first when clause is tested with: User.===(resource) or User === resource, and the second with AdminUser.===(resource). As User and AdminUser are Class objects, they use the Module#=== method. The important thing here is be aware that this method is not commutative, it is a class method which accepts any object as param, and return true if the param is an instance of that class.

Upvotes: 2

svonborries
svonborries

Reputation: 73

Thank you very much Alejandro,

You were right with my puts error, actually I'm embarrassed by such an obvious mistake with the return of the method... For some extrange reason that I don't know the Case doesn't work... It did for the AdminUser model, but never for the User model... If anybody has an idea, let me know because I hate state with doubts, and right know I'm short of time to workaround...

I did this small changes to the code, and works for me... I know it is a hard and ugly code, but it does the job, maybe later i got some time to make a better code.

def after_sign_in_path_for(resource)
  return dashboard_index_path if resource.class == User
  return admin_root_path
end

Thank you very much!

Upvotes: 0

Related Questions