我的代码:
#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异常中捕获?
解决方法
您的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”块中.