我以为ruby是同步语言..但为什么呢?

Jay*_*ong 0 ruby ruby-on-rails

我有我的rails应用程序并试图通过添加一个名为cancancan的gem制作的方法来添加权限.所以下面有两种方法.

 def find_review
   @review = Review.find(params[:id])
 end

 def authorize_user!
   unless can? :manage, @review
     redirect_to product_path(@review.product)
   end
 end
Run Code Online (Sandbox Code Playgroud)

有两种情况.案例1:调用destroy内部的方法动作

def destroy
  find_review
  authorize!
  @product = @review.product
  @reviews = @product.reviews
  @review.destroy
end
Run Code Online (Sandbox Code Playgroud)

和案例2:使用before_action方法调用方法

before_action :find_review, :authorize!, only: [:destroy]

def destroy
  @product = @review.product
  @reviews = @product.reviews
  @review.destroy
  redirect_to product_path(@product), notice: 'Review is deleted'
end
Run Code Online (Sandbox Code Playgroud)

我使用before_action(案例2)甚至在调用操作之前重定向未经授权的用户,这样才有意义.我想知道的是在案例1中,为什么授权方法在销毁审核之前不会中断和重定向用户?它实际上重定向,但删除审查后.但我认为红宝石是同步的..

Ser*_*sev 5

正如其他人已经注意到的那样,你authorize!不会中断请求,只会添加一个标题,然后继续进行破坏等等.从嵌套方法调用中断流的一种很好的可靠方法是引发异常.像这样的东西:

class ApplicationController
  NotAuthorizedError = Class.new(StandardError)

  rescue_from NotAuthorizedError do
    redirect_to root_path
  end

end

class ReviewsController < ApplicationController
  def authorize!
    unless can?(:manage, @review)
      fail NotAuthorizedError
    end
  end

  def destroy
    find_review
    authorize! # if user is not authorized, the code below won't run
               # because of the exception
    @product = @review.product
    @reviews = @product.reviews
    @review.destroy
  end
end
Run Code Online (Sandbox Code Playgroud)

更新

您可以通过集成cancan来解决问题,因为它确实包含异常提升authorize!.你应该能够做到这一点:

  def destroy
    find_review
    authorize! :manage, @review # can raise CanCan::AccessDenied
    @product = @review.product
    @reviews = @product.reviews
    @review.destroy
  end
Run Code Online (Sandbox Code Playgroud)

或更好

  load_and_authorize_resource

  def destroy
    @product = @review.product
    @reviews = @product.reviews
    @review.destroy
  end
Run Code Online (Sandbox Code Playgroud)