In my controller controller, I have use Date.new
to create a date object to be passed in my 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 40
for the day param, the Date.new
fails (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
).
I tried various conditionals (if
and unless
statements) to raise ActiveRecord::RecordNotFound
if that fails, but it returns the 500 error before running the conditional (and therefor never returning a 404).
Does anybody know a better way to handle that, or a way to allow the Date.new
to fail more gracefully so that the conditional statement can run?
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_from
method of ApplicationController:
class ApplicationController < ActionController::Base
rescue_from 'ArgumentError do
render(:partial => 'exceptions/argument_error', :layout => 'application', :status => :not_found)
end
end
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.
Further, if you rescue all ArgumentError
s 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.
I've put this in the 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With