Rails 4 设计,after_sign_in_path_for(资源) 总是重定向到模型的显示操作

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

我坚持使用设计方法 after_sign_in_path_for,这就是问题所在... 我有两个模型 UsersAdminUsers 我正在使用 active_admin gem

我的routes.rb文件,看起来像这样:

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

好的...在我的 application_controller.rb 中,我尝试了以下代码:

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

如您所见,我有一些 puts 只是为了在我的控制台中检查我的 case 是否有效...确实如此,它确实有效,这是我的控制台: 我正在尝试以 AdminUser 身份登录到 active_admin

admin_root_path
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)

如您所见,Devise 将我重定向到 current_admin_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)

在这两种情况下,Devise 都在做同样的事情...重定向到每个模型的显示操作,我已经尝试将此代码放在自定义 registrations_controller.rb 中,并且相同... 也许我遗漏了一些明显的东西,我不是 Devise 方面的专家,有人知道我做错了什么吗?

rake routes命令的相关结果

....
....
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

请试试这个:

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

有两点需要注意:我使用 resourse.class 我认为这是问题中的错字,而不是代码中的错字(因为它打印的是 puts)。其次,after_sign_in_path 必须 return 一个 url,并且您的代码的最后一个操作是 puts,即 return 和 nil

你也可以试试:

def after_sign_in_path_for(resource)
  dashboard_index_path 
end

第一次看到 after_sign_in_path_for 工作。并以此为起点向前迈进。

如果这一切都不起作用,请发布 sign_inlogin 路线。

编辑:在阅读了您的 post 之后,我意识到这种情况不起作用(错误:有效),因为这种情况与 === 一起使用并且resource.class === AdminUser 总是 return false(是不同的对象)。您必须要求 resource.class == AdminUserresource.is_a?(AdminUser)。更多案例匹配 here。我还更新了 after_sign_in_path 方法。

编辑 2 在阅读@CJBrew 评论和 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"

我可以说这段代码一定能正常工作:

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

因为 case 使用 === 并且 when 值作为对象,case 值作为参数。在这种情况下,第一个 when 子句用 User.===(resource)User === resource 测试,第二个用 AdminUser.===(resource) 测试。由于 UserAdminUser 是 Class 对象,因此它们使用 Module#=== method。这里重要的是要注意这个方法是不可交换的,它是一个接受任何对象作为参数的 class 方法,如果参数是 class 的实例,则 return 为真.

非常感谢亚历杭德罗,

你对我的 puts 错误是正确的,实际上我对 return 如此明显的错误感到尴尬的方法... 由于一些我不知道案例不起作用的奇怪原因......它对 AdminUser 模型有效,但对 User[=23= 无效] 模型...如果有人有想法,请告诉我,因为我讨厌有疑问的状态,并且知道我没有时间解决...

我对代码做了这个小改动,对我有用...我知道这是一个难看的代码,但它完成了工作,也许以后我有时间制作更好的代码。

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

非常感谢!