30

我如何覆盖设计 gem的current_user。 实际上我需要为移动应用程序添加网络服务。

目前的设计是管理网络应用程序的会话和“当前用户”。

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

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

我是否需要将设计 gem 修改为插件?或者是其他东西 ?
请详细解释,因为我是 Rails 新手。

亲切的问候,

4

4 回答 4

58

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

# in application_controller.rb

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

def current_user
  if params[:user_id].blank?
    devise_current_user
  else
    User.find(params[:user_id])
  end   
end
于 2012-04-27T11:36:27.677 回答
6

建议对方法进行别名的另一个答案实际上不是最佳解决方案。道格英语的评论是最好的解决方案:

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

原因如下:

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

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

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

于 2014-09-02T22:52:04.857 回答
1

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
于 2017-02-19T19:07:42.187 回答
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上述过时吗?

于 2015-10-28T08:52:13.073 回答