Ruby-on-rails 为无效日期引发 ActiveRecord::RecordNotFound(或任何 404 状态)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3407891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
raise ActiveRecord::RecordNotFound (or any 404 status) for invalid date
提问by James Pierce
In my controller controller, I have use Date.newto create a date object to be passed in my ActiveRecord.
在我的控制器控制器中,我已经Date.new创建了一个要在我的 ActiveRecord 中传递的日期对象。
end_range = Date.new(params[:year].to_i, params[:month].to_i, params[:day].to_i).end_of_day.to_formatted_s(:db)
The problem with this above is that if a user tried to change the parameters in the URL manually, such as entering 40for the day param, the Date.newfails (as expected). However, I would rather not have a 500 error if a user typed in something like that, but instead a 404 error (because you will never actually be able a record with a day of 40).
上面的问题是,如果用户尝试手动更改 URL 中的参数,例如输入40日期参数,则会Date.new失败(如预期)。但是,如果用户输入类似的内容,我宁愿不会出现 500 错误,而是出现 404 错误(因为您实际上永远无法记录 1 天40)。
I tried various conditionals (ifand unlessstatements) to raise ActiveRecord::RecordNotFoundif that fails, but it returns the 500 error before running the conditional (and therefor never returning a 404).
我尝试了各种条件(if和unless语句),raise ActiveRecord::RecordNotFound如果失败,但它在运行条件之前返回 500 错误(因此从不返回 404)。
Does anybody know a better way to handle that, or a way to allow the Date.newto fail more gracefully so that the conditional statement can run?
有没有人知道更好的处理方法,或者允许Date.new更优雅地失败以便条件语句可以运行的方法?
回答by tadman
In this case you might rescue one exception and raise another if you'd like to re-map exceptions that aren't handled into the kind that are:
在这种情况下,如果您想将未处理的异常重新映射为以下类型,您可能会拯救一个异常并引发另一个异常:
def show
begin
end_range = Date.new(...)
rescue ArgumentError
# Invalid date
raise ActiveRecord::RecordNotFound
end
rescue ActiveRecord::RecordNotFound
render(:partial => 'not_found', :layout => 'application', :status => :not_found)
end
It might be more efficient to simply render and fail right away though.
不过,简单地渲染并立即失败可能更有效。
def show
begin
end_range = Date.new(...)
rescue ArgumentError
return render(:partial => 'date_not_found', :layout => 'application', :status => :not_found)
end
end
You can also do this in a more sweeping sense using the rescue_frommethod of ApplicationController:
您还可以使用rescue_fromApplicationController的方法以更全面的方式执行此操作:
class ApplicationController < ActionController::Base
rescue_from 'ArgumentError do
render(:partial => 'exceptions/argument_error', :layout => 'application', :status => :not_found)
end
end
回答by ice cream
I think it makes more sense to rescue an invalid date error with a useful message. This is a common problem when people select 30 February for example. I would rather send them back to the form in question and tell them why they are getting sent back. A 404 would be wrong in most cases, since the error is invalid user input, not an invalid URL.
我认为用有用的消息挽救无效的日期错误更有意义。例如,当人们选择 2 月 30 日时,这是一个常见问题。我宁愿将他们送回有问题的表格,并告诉他们为什么他们会被送回。大多数情况下 404 是错误的,因为错误是无效的用户输入,而不是无效的 URL。
Further, if you rescue all ArgumentErrors then you won't get notified of other code-related bugs. So if it's not a date error then I'm re-raising the error. Unfortunately we have to change the exception type to avoid a loop.
此外,如果您拯救所有ArgumentErrors,那么您将不会收到其他与代码相关的错误的通知。因此,如果这不是日期错误,那么我将重新提出错误。不幸的是,我们必须更改异常类型以避免循环。
I've put this in the application_controller:
我把它放在 application_controller 中:
rescue_from ArgumentError do |exception|
if exception.message == 'invalid date'
flash[:error] = exception.message
redirect_to request.referer ? :back : root_url
else
raise StandardError, exception.message, exception.backtrace
end
end

