我有一个更新方法,它使用具有自己的渲染调用的保存和删除方法。以下是代码:
更新方法:
def update_book
self.delete_book
params[:Name] = params[:NewName]
self.save_book
end
删除方法:
def delete_book
# Do something
rescue BookDoesNotExist => exception
render status: 404
return
end
head 200
end
保存方法:
def save_book
# Do something
rescue BookDoesNotExist => exception
render status: 404
return
end
rescue BookAlreadyExist => exception
render status: 409
return
end
head 200
end
当我使用某些输入运行时,系统会抛出“AbstractController::DoubleRenderError
”错误以及一些消息“Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return
”
我理解这是因为在我传递的输入中,删除和保存方法都抛出了异常。我该如何处理这种情况?
进行一些研究我了解到我需要使用重定向。所以我理解当我的delete方法抛出异常/渲染时我应该返回并且不应该调用save方法。
以下是我使用redirect_to尝试的内容:
更新方法:
def update_book
redirect_to action: self.delete_book and return if status=404 end
params[:Name] = params[:NewName]
self.save_book
end
我做得对吗还是还有其他最好的方法来处理重定向吗?
答案 0 :(得分:2)
当您的delete_book
或save_book
方法收到异常后,他们会呈现内容然后返回,这是正确的。
但是return
会将执行返回给调用者方法,即update_book
。此调用方法不知道发生的异常,因此将完成其工作并呈现它必须呈现的内容。
要解决此问题,您的delete_book
或save_book
方法需要向调用方返回成功状态,如下所示:
def delete_book
# ... Do something
rescue BookDoesNotExist => exception
render status: 404
return false
end
head 200
true
end
然后您的调用方法将检查此状态:
def update_book
return unless self.delete_book
params[:Name] = params[:NewName]
return unless self.save_book
end
另一种可以让您的代码远离那些繁重的异常测试的替代方法是使用您的控制器rescue_from
。
在ApplicationController
:
class ApplicationController < ActionController::Base
rescue_from BookDoesNotExist, with: :redirect_book_not_existing
private
def redirect_book_not_existing
render status: 404
end
end
从现在开始,当控制器收到BookDoesNotExist
异常时,执行将停止并执行render status: 404
行。当然,您不能rescue
其他方法中的例外情况,例如:
def delete_book
# Do something
head 200
end
您的代码将更加清晰