如何覆盖设计宝石的 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的新手。
亲切的问候,
答案 0 :(得分:49)
根据模块Devise::Controllers::Helpers,current_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