首页 > 解决方案 > 当 ActiveRecord::RecordNotFound 未检测到用户等于 nil 时如何处理

问题描述

我只是在学习编程,尤其是 Ruby on Rails。我目前面临的问题是,我怀疑在干净的代码和避免我的代码异味或其他可能的问题方面,以哪种方式处理我的问题更好。

所以基本上,我有 users_controller 来检查我jwt的是否有效:我对其进行解码,撤回user_id并在 DB 中查找用户id

 def login
    user = decoded_user(permitted_params[:jwt])
    render json: user
  rescue ActiveRecord::RecordNotFound, JWT::DecodeError
    render status: 401, json: { error: 'invalid token' }.to_json
  end

如您所见,如果 jwt 无效或未找到用户,它必须呈现401 error,但不知何故,当用户存在时nilrescue ActiveRecord::RecordNotFound不会检测到它并200 status在我想要它时呈现401。当jwt有效或为空时,一切正常。

我想把它包装成if else块,以防万一nil对我来说它似乎不是很熟练。你能帮我重构一下吗?谢谢!

标签: ruby-on-railsrubyruby-on-rails-3jwt

解决方案


有两种不同的方法可以通过最小的更改来处理这个问题。

找比!

首先是确保在找不到用户时引发异常。您已经使用find_by文档中说:

如果没有找到记录,则返回nil

对于 Rails 中的许多查找器方法,都有以 a!结尾的变体。指示在 Rails 上下文中该!方法将引发异常。对于find_by,存在相同的find_by!变体。此方法的文档告诉您,它与 完全一样find_by,只是它不会返回nil,而是引发异常。

替换find_bydecode_userfind_by!您的方法应该按预期工作。

避免异常

引发异常通常被视为一种反模式。这有很多不同的原因,但经常使用的一个论点是异常缓慢。如果您查看 Rails 在使用脚手架时生成的代码,您会发现控制器操作通常如下所示:

def create
  @test = Test.new(test_params)

  if @test.save
    redirect_to @test, notice: 'Test was successfully created.'
  else
    render :new
  end
end

您也可以为您的方法使用相同的模式。首先,解码用户。然后检查用户是否存在,例如使用user.present?. 基于此,要么返回成功,要么返回失败。

您会在 Rails 中看到很多这种模式,我建议您在此处重构代码以遵循它...


推荐阅读