-
-
Notifications
You must be signed in to change notification settings - Fork 504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolves #4922 #4925
base: main
Are you sure you want to change the base?
Resolves #4922 #4925
Conversation
As additional background -- for unknown reasons, @gabeparra01 was unable to easily recreate the issue in the way described in the issue -- we have no idea why at this point! |
@gabeparra01 Thanks for taking this on. It is a palpable improvement from a functional pov. I'm not keen on them losing all their filters (including but not exclusive to the badly formatted date) when there is an error in the date format. But it's better than a 500 error, IMO. |
There are also some cases where I put in an improperly formatted date (say, November 10-16, 2024 on donations), and it doesn't give me an error, it just goes back to the default. Those don't lose the other filters, though. |
@cielf That's a great catch! I did not realize that the reports controller does not have an index action. So if I entered There are 2 problems with this fix though:
|
Asking @dorner to jump in with advice on this one. |
@cielf I am happy to help! I tried passing filters in the redirect in this way: I am not sure where the error is coming from. I debugged and confirmed that:
The only other cause I can think of is maybe it is related to the JavaScript issue that @coalest identified here: #4922 (comment) I can start looking into the JavaScript issue as well, but it will take some time. @cielf @coalest Please let me know what your thoughts are |
Question: Do we have to redirect at all? If we fail to parse the date, can we just use the default date range and flash an error/warning that the date range couldnt be parsed so it was ignored? Then all the other filters are saved at least, and we don't have to worrrt about the redirection logic. |
Flashing an error/warning does require a redirect. If you don't do a redirect then you end up in a weird browser state where refreshing the page resubmits the original form. I think it's safe to say that we will not be using filters except in GET requests. So if your solution only works for GET, I think that's fine. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, if they are going to lose their other filters, we should mention that in our error -- Maybe something like "Date range '[what they entered]' not properly formatted. Filters reset."
@@ -13,6 +13,7 @@ class ApplicationController < ActionController::Base | |||
helper_method :current_role | |||
|
|||
rescue_from ActiveRecord::RecordNotFound, with: :not_found! | |||
rescue_from Date::Error, with: :invalid_date |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we go with this approach, maybe could we rescue from a custom error for this purpose like InvalidDateRange
or something? Because since Date::Error
is from the standard library we might at some point raise this error in a different place and we may not want to respond in the same way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah good point! I created the new custom error and updated the unit test here
@@ -115,6 +116,12 @@ def swaddled | |||
response.headers["swaddled-by"] = "rubyforgood" | |||
end | |||
|
|||
def invalid_date | |||
flash[:error] = "Date range not properly formatted." | |||
params["filters"]["date_range"] = helpers.default_date |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this line necessary? Won't the default date range be selected after a redirect anyways?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching that! Manually resetting the date_range is no longer necessary with our latest approach. Removed it here
@dorner Maybe there's something I don't understand about flashes with GET requests. But to me, a user clicks the filter button and requests HTML. On the server we should be able to send back HTML that includes a flash message. At a glance the following seems to work without any issues: diff --git a/app/helpers/date_range_helper.rb b/app/helpers/date_range_helper.rb
index cc73af80..82a71c16 100644
--- a/app/helpers/date_range_helper.rb
+++ b/app/helpers/date_range_helper.rb
@@ -36,8 +36,12 @@ module DateRangeHelper
def selected_interval
date_range_params.split(" - ").map do |d|
Date.strptime(d, "%B %d, %Y")
- rescue
- raise "Invalid date: #{d} in #{date_range_params}"
+ rescue Date::Error
+ flash.now[:notice] = "Invalid date param provided. Reset to default date range"
+ return default_date.split(" - ").map do |d|
+ Date.strptime(d.to_s, "%B %d, %Y")
+ end
end
end I don't know if there would be any edge cases, but if it is possible to do the above I think it would provide the best user experience. Because all of their other filters are preserved, only the date range is lost but we have no way of parsing the date range anyways. |
@gabeparra01 Regarding your question about the other related issue (why these invalid date params are appearing at least some of the time), I think it could probably be a separate PR to keep things easy for the team here to review. Note: Although the javascript normally fixes the date range to be valid, I think the issue is strictly server side. Here is an example test that I believe should be passing but is currently failing. Should be helpful if you do want to tackle the other part of this issue. diff --git a/spec/requests/distributions_requests_spec.rb b/spec/requests/distributions_requests_spec.rb
index a4346247..d33a9275 100644
--- a/spec/requests/distributions_requests_spec.rb
+++ b/spec/requests/distributions_requests_spec.rb
@@ -70,6 +70,17 @@ RSpec.describe "Distributions", type: :request do
expect(response).to be_successful
end
+ it "fills in the date range filter with a valid date range" do
+ get distributions_path
+
+ page = Nokogiri::HTML(response.body)
+ default_date_range = page.at_css("#filters_date_range")["value"]
+
+ expect {
+ default_date_range.split(" - ").map { |d| Date.strptime(d, "%B %d, %Y") }
+ }.to_not raise_error
+ end
+
it "sums distribution totals accurately" do
create(:distribution, :with_items, item_quantity: 5, organization: organization)
create(:line_item, :distribution, itemizable_id: distribution.id, quantity: 7) |
Resolves #4922
Description
The code changes in this PR add error handling for the date range logic used in the following pages/workflows:
The approach I chose was to add a rescue method in
application_controller.rb
for theDate::Error
that was being raised indate_range_helper.rb
. The main reason that I chose this approach is because we need to redirect to the correct child controller's action method after handling the error. I think it is possible to redirect to the correct controller from the Helper class but it seems like an anti-pattern and would make future maintenance challenging.One drawback of this approach is that the redirect is defaulting to the index action of the child controller. So if there is a future workflow that uses the date range logic in a different controller action other than index, this code could cause an unexpected redirect. If that happens, a possible fix could be adding a new method in the child controller and then calling this method with
super
.Type of change
How Has This Been Tested?
I spent a lot of time trying to write new Rspec tests around the date range error handling but did not achieve much success. The TLDR summary is that I wanted to avoid refactoring any date range logic because of the long list of workflows that it is used in. Even though it would make the code much easier to unit test.
Here are some of the issues I ran into while trying to add unit tests:
setup_date_range_picker
method in application_controller.rb is a protected method. Calling this method directly will cause an error in RSpecapplication_controller.rb
,DateRangeHelper.rb
and one of the child controllers. This would take a long time to setup properly and might be brittle.Date::Error
rescue method inapplication_controller.rb
using RSpec. I think it would require a full route/API test in one of the child controllersScreenshots and Screen Recordings
Products Drive Manual Test.zip
Distributions Manual Test.zip