ruby-on-rails – self.errors [:base] <<在ActiveRecord事务块中

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – self.errors [:base] <<在ActiveRecord事务块中前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
除非用户不符合某些条件,否则我想更新@some_instance.我把标准检查和@ some_instance.save放了!在事务块中,如果其中任何一个失败,则不进行任何事务.这很好用,但我无法返回正确的错误消息.如果用户不符合条件,我想返回原因,或者如果@some_instance没有保存,我想返回该错误.

我的代码

#some_controller.rb
begin
  Some_Class.transaction do
    return render json: { error: @user.errors },status: :payment_required,location: new_payment_path unless @user.meets_criteria
    @some_instance.save!
  end
rescue ActiveRecord::RecordInvalid => exception
  render :json => { :error => exception.messages },status: :unprocessable_entity
rescue => error
  # handle some other exception
end

#User.rb
def meets_criteria
  self.errors[:base] << "Does not meet criteria"
  return false
end

我面临的问题是:当meet_criteria方法返回false时,我希望返回渲染json行来执行.相反,它会在“rescue => error”中捕获错误.

永远不会执行返回渲染json.

更新:

@Gen建议使用before_action而不是在事务块中调用meet_criteria.我认为这是一个更好的实现,但我仍然好奇为什么永远不会调用返回呈现.是因为ActiveRecord会引发错误吗?如果是这样,不应该在RecordInvalid异常中捕获?

解决方法

@TheJKFever,我不确定你的代码是否应该跳转到任何救援块(好吧,我确实通过运行它来确认).

您的some_validation方法返回false,因此“除非@ user.some_validation”的计算结果为true,并使用以下日志输出执行呈现:

Completed 402 Payment required in 128ms

{"error":{"base":["Some error message"]}}

有关RecordInvalid的详细信息,请参阅ActiveRecord::RecordInvalid API.即,“由保存提升!并在记录无效时创建!”.

所以,你的“救援ActiveRecord :: RecordInvalid =>异常”应该处理“@ some_instance.save!”中的异常.声明而不是您的自定义验证.

在您的验证中,您实际上没有引发ActiveRecord :: RecordInvalid异常的代码,并且可能因另一个错误而失败,这很容易通过详细输出来检查.

为了将some_validation用于“self.errors [:base]<<”首先,您需要将以下语句添加到您的用户模型: validate:some_validation 在这种情况下,如果你调用“@ user.save!”而不是“@ some_instance.save!”,你将陷入“救援ActiveRecord :: RecordInvalid =>异常”块.

PS:@TheJKFever,我在下面看到你的一条评论,想澄清一些事情.验证具有明确定义的目的,即在保存之前验证模型,然后您需要的不是模型验证.您实际需要的是控制器上的before_action,它将检查您的用户是否已准备好用于此类操作(将其视为控制器验证).是的,您可能需要在您的用户模型上使用某种方法来进行检查.

更新(问题更新后)

@TheJKFever,正如我前面提到的,当我实现你的代码时,我能够执行“return render json:{error:@ user.errors} …”.因此,如果它失败了,它必须是在meet_criteria调用期间的一些异常,但它不是RecordInvalid异常.由于您将meet_criteria包装到事务中,这意味着它可能会执行一些您希望在@ some_instance.save时回滚的数据库更改!没有成功.最好用meet_criteria包装相同的救援块并找出答案.你创造了!还是保存! meet_criteria中有什么东西?如果是这样,那么它也可以抛出RecordInvalid异常.问题是你的代码RecordInvalid可以被meet_criteria和@ some_instance.save!抛出,并且没有办法在代码中看到哪一个.在任何情况下,如果您使用rescue包装您的meet_criteria,您将能够从中发送您的渲染错误请求.如果您决定使用before_action过滤器,则必须将整个事务移动到其中(假设它需要数据的完整性).

关键是只有在保存的情况下才会抛出ActiveRecord :: RecordInvalid异常!还是创造!数据无效导致失败.在您的代码中可能不是这种情况,并且抛出了一些其他异常,并且最终出现在“rescue => error”块中.

猜你在找的Ruby相关文章