繁体   English   中英

如何通过在Ruby中传递块来进行救援?

[英]How to rescue by passing a block in Ruby?

我在一个控制器中定义了自己的方法authorize_user ,如下所示:

    def authorize_user
      if !((current_user.has_role? :admin, @operator) || (current_user.has_role? :super_admin))
        raise CanCan::AccessDenied
      end
    end

我想从CanCan异常(或其他任何异常)中解救出来。 我已在我的应用程序中使用过Rolify。 如何通过自定义消息来救援并重定向到我的应用程序的root_url

我尝试了以下选项,但没有一个起作用:

尝试1:

rescue CanCan::AccessDenied do |exception|
    redirect_to root_url, :alert => exception.message
end

在这种情况下的syntax error, unexpected keyword_do, expecting '('syntax error, unexpected keyword_do, expecting '('

尝试2:

rescue CanCan::AccessDenied
  redirect_to root_url, :alert => "Unauthorized Access"

在这种情况下的错误: Render and/or redirect were called multiple times in this action

我该如何解决这个问题?


这是我的控制器代码:

class CabsController < ApplicationController
  before_action :set_cab, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!
  after_action :authorize_user

 # Some basic CRUD actions

 private

    def set_cab
      @cab = Cab.find(params[:id])
      @operator = Operator.find(params[:operator_id])
    end


    def cab_params
      params.require(:cab).permit(:category, :number)
    end

    def authorize_user
      if !((current_user.has_role? :admin, @operator) || (current_user.has_role? :super_admin))
        raise CanCan::AccessDenied
      end
    end
end

我认为您可以尝试使用rescue_from方法。

例如,您的ApplicationController如下所示:

class ApplicationController < ActionController::Base
  rescue_from CanCan::AccessDenied, with: :not_authorized

  #other stuff      

  private
  def not_authorized
    redirect_to root_url, alert: "Unauthorized Access"
  end
end

由于使用更多代码更新了该问题,因此这里提供了更多信息:

一些建议:

  • 也将:authorize_userbefore_action 这样,即使在不允许用户执行操作的情况下,您也不必担心操作中运行的代码。
  • 您可能还需要添加与:set_cab相同的:only选项,因为您使用了@operator实例变量。
  • 最后,个人代码样式首选项是我应该更改if ! unless增加阅读量。

尝试redirect_to(...) and return

同意Jakob W,我想指出,授权(和认证)必须仅在执行操作之前执行。 如果已经完成数据库事务,对文件系统的读取/写入等操作,那么引发任何授权和异常的目的是什么?

并且使用before_actionRender and/or redirect were called multiple times in this action没有问题-在控制器方法调用之前的异常处理中将只有一个重定向。

因此,我推荐下一个代码(更新了Jakob W的示例):

class CabsController < ApplicationController
  #...
  before_action :authorize_user

  private
    #...
    def authorize_user
      if !((current_user.has_role? :admin, @operator) || (current_user.has_role? :super_admin))
        raise CanCan::AccessDenied
      end
    end
end


class ApplicationController < ActionController::Base
  rescue_from CanCan::AccessDenied, with: :not_authorized

  #other stuff      

  private
  def not_authorized
    redirect_to(request.referrer || root_path), alert: "Unauthorized Access"
  end
end

我可以推荐另一个授权宝石吗? 我认为这是灵活且易于使用的-pundit( https://github.com/elabs/pundit )。 github上的页面有一些关于授权的有用技巧。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM