在哪里覆盖devise gem的current_user helper方法

时间:2012-04-27 11:14:17

标签: ruby-on-rails-3 authentication ruby-on-rails-3.1 rubygems devise

如何覆盖设计宝石的 current_user 实际上我需要为mobile-app添加web服务。

目前设计是管理会话和网络应用程序的'current_user'。

现在,移动应用会将user_id发送到服务器。我需要像这样覆盖当前用户

def current_user
  if params[:user_id].blank?
    current_user
  else
    User.find(params[:user_id])
  end   
end

我是否需要修改devise gem作为插件?或其他什么?
请详细解释,因为我是rails的新手。

亲切的问候,

4 个答案:

答案 0 :(得分:49)

根据模块Devise::Controllers::Helperscurrent_user(与所有其他设计助手一起)被添加到ApplicationController,这意味着您可以用这种方式覆盖它:

# in application_controller.rb
alias_method :devise_current_user, :current_user
def current_user
  if params[:user_id].blank?
    devise_current_user
  else
    User.find(params[:user_id])
  end   
end

答案 1 :(得分:5)

另一个答案表明混淆方法实际上不是最好的解决方案。 Doug English的评论是最好的解决方案:

# In ApplicationHelper
def devise_current_user
   @devise_current_user ||= warden.authenticate(:scope => :user)
end

原因如下:

假设您在控制器中包含了ApplicationHelper。如果你的ApplicationHelper中需要一个依赖于devise_current_user的方法,给定控制器内的别名解决方案,那你就不走运了。

但是使用上面的显式方法定义,您可以将定义移动到帮助程序并从其他方法调用它,您仍然可以将它包含在控制器中。

这很有用,例如,当您开发用户模拟解决方案时,您需要在视图中显示两个不同的用户,一个用于真实管理员(devise_current_user),另一个用于模拟用户(current_user) )。

答案 2 :(得分:0)

假设我们可以信任我们的会话数据(这取决于你是否在未经适当授权的情况下将用户输入放在那里),这可能会引起关注:

module Concerns
  module ControllerWithImpersonation
    extend ActiveSupport::Concern

    included do
      helper_method :devise_current_user
    end

    def current_user
      if session[:impersonated_user_id].blank?
        devise_current_user
      else
        User.find(session[:impersonated_user_id])
      end
    end

    def devise_current_user
      @devise_current_user ||= warden.authenticate(:scope => :user)
    end

  end
end

我现在正在项目中使用它。

一个小问题(在答案中,对不起)......我应该知道设计devise_current_user过时的设计或监护人的任何变化吗?

答案 3 :(得分:0)

Limbo-Peng的答案很棒,但可以稍作改进,以确保只有管理员才能做到这一点:

您还需要在User类上定义is_admin?方法或is_admin属性。

您可能还想使用与user_id不同的密钥,因此它永远不会与您的常规参数冲突。

# to impersonate another user, e.g. for customer support
# only admins can do this..
#
alias_method :devise_current_user, :current_user
def current_user
  if ! params[:user_id].blank? \
     && devise_current_user && devise_current_user.is_admin? 
    User.find(params[:user_id])
  else
    devise_current_user
  end
end