我有一个ProjectsController
,除new
和index
之外的所有操作都限制在admins
。我在我的控制器中添加了一个before_filter,如
before_action :authorize_admin!, except: [:index, :show]
并且before_filter
看起来像这样。
def authorize_admin!
check_login!
unless current_user.admin?
redirect_to root_path, alert: "You're not authorized"
end
end
check_login!
是ApplicationController
中的一种方法,重定向到root_path
用户未登录。
def check_login!
flash[:alert] = 'You need to sign up or sign in before continuing'
redirect_to login_path unless current_user
end
current_user
是一种在用户会话存在时返回用户记录的方法。(与错误无关)
问题是当我尝试访问/projects/4/edit
而未登录时,我收到了undefined method
管理员? for nil:NilClass error. In the before filter,
check_login!is executed first and if the user's not logged in, he should be redirected to the
root_path`。这显然意味着即使在重定向之后,执行也不会终止。
在Web控制台中,我尝试执行check_login!
,这次我遇到了AbstractController::DoubleRenderError: Render and/or redirect were called multiple times in this action.
错误。它暗示我使用redirect_to(..) and return
。
虽然我知道它不起作用,但我尝试将check_login?
方法修改为
def check_login!
redirect_to login_path, alert:
'You need to sign up or sign in before continuing' and return unless current_user
end
在查看SO线程后,我也尝试了以下内容。
return redirect_to login_path, alert:
'You need to sign up or sign in before continuing` unless current_user
我认为它失败导致它返回被调用者,authorize_admin!
方法,并且当current_user为nil时,我得到undefined method
错误。
我该如何解决这个问题?
注意:我不想在check_login!
中重复authorize_admin!
代码,因为它违反了DRY。
答案 0 :(得分:1)
如果过滤器重定向,则后续过滤器和操作本身不会运行,但过滤器本身会继续。在您的情况下,在调用check_login!
后,authorize_admin!
过滤器将继续执行。
如果检查通过,您可以更改check_login!
以返回true,如果没有当前用户,则返回false。然后authorize_admin
可以做
check_login! || return
或者,performed?
方法告诉您是否发生了渲染或重定向,以便您可以
check_login!
return if performed?