before_action 中的 render/head 不会停止执行其余操作

Rah*_*hul 5 ruby-on-rails before-filter ruby-on-rails-4

我有一个私有方法authenticate_user!在我的应用程序控制器中,它验证标头中的令牌并返回用户记录(如果找到)。这是它的样子。

def authenticate_user!
  # authenticate
  @current_login = Login.where(oauth2_token: bearer_token).first
  head 401 if @current_login.nil? # and return
  @current_user = @current_login.user
  head 401 if @current_user.nil? 
end
Run Code Online (Sandbox Code Playgroud)

我使用此方法对控制器中的用户进行身份验证,如下所示。

class AddressesController < ApplicationController
   before_action :authenticate_user!

   def some_action
      data = @current_user.some_associated_records
      render json: {data: data}
   end
end
Run Code Online (Sandbox Code Playgroud)

理想情况下,当找不到登录名或找不到相应的用户时,我应该从authenticate_user 获得 401 响应!方法。

相反,我总是收到 500 内部服务器错误。不知何故,它head 401 if current_login.nil?不会停止执行链。即使渲染状态:401 也不起作用。

根据我的理解,如果 Rails在 before_action 过滤器中找到 arender或 a命令,则它会返回。head我缺少什么?

编辑:

以下解决方案有效:

      private

      def authenticate_user!(*)
        @current_login = Login.where(oauth2_token: bearer_token).first!
        @current_user = @current_login.user
        rescue ActiveRecord::RecordNotFound
          head 401
      end
Run Code Online (Sandbox Code Playgroud)

然而我仍然很困惑为什么原来的方法不起作用。

sfa*_*ate -1

正如@Rahul提到的(before_action 中的 render/head 不会停止执行操作的其余部分),当您尝试从中获取user@current_login步骤nil中的 a 时,该步骤会发生 500 错误。

head方法只是调用render nothing: true提供的状态。并且render不会破坏任何执行链。

根据上面的注释,我建议像这样重写它:

def authenticate_user!
  @current_login = Login.find_by(oauth2_token: bearer_token)
  @current_user = @current_login&.user
  head 401 if @current_user.nil? 
end
Run Code Online (Sandbox Code Playgroud)