DEV: Support filtering by date columns on /filter route (#21233)

This commit adds support for the following date filters:

1. `activity-before:<YYYY-MM-DD>` which filters for topics that have been bumped at or before given date
2. `activity-after:<YYYY-MM-DD>` which filters for topics that have been bumped at or after given date
3. `created-before:<YYYY-MM-DD>` which filters for topics that have been created at or before given date
4. `created-after:<YYYY-MM-DD>` which filters for topics that have been created at or after given date
5. `latest-post-before:<YYYY-MM-DD>` which filters for topics with the
latest post posted at or before given date
6. `latest-post-after:<YYYY-MM-DD>` which filters for topics with the
latest post posted at or after given date

If the filter has an invalid value, i.e string that cannot be converted
into a proper date in the `YYYY-MM-DD` format, the filter will be ignored.

If either of each filter is specify multiple times, only the last
occurrence of each filter will be taken into consideration.
This commit is contained in:
Alan Guo Xiang Tan
2023-04-27 14:43:47 +07:00
committed by GitHub
parent e5ec0b84a9
commit 141555136a
2 changed files with 140 additions and 6 deletions

View File

@@ -36,12 +36,24 @@ class TopicsFilter
filter_values = extract_and_validate_value_for(filter, values)
case filter
when "activity-before"
filter_by_activity(before: filter_values)
when "activity-after"
filter_by_activity(after: filter_values)
when "category"
filter_categories(values: key_prefixes.zip(filter_values))
when "created-after"
filter_by_created(after: filter_values)
when "created-before"
filter_by_created(before: filter_values)
when "created-by"
filter_created_by_user(usernames: filter_values.flat_map { |value| value.split(",") })
when "in"
filter_in(values: filter_values)
when "latest-post-after"
filter_by_latest_post(after: filter_values)
when "latest-post-before"
filter_by_latest_post(before: filter_values)
when "likes-min"
filter_by_number_of_likes(min: filter_values)
when "likes-max"
@@ -99,8 +111,21 @@ class TopicsFilter
private
YYYY_MM_DD_REGEXP =
/^(?<year>[12][0-9]{3})-(?<month>0?[1-9]|1[0-2])-(?<day>0?[1-9]|[12]\d|3[01])$/
private_constant :YYYY_MM_DD_REGEXP
def extract_and_validate_value_for(filter, values)
case filter
when "activity-before", "activity-after", "created-before", "created-after",
"latest-post-before", "latest-post-after"
value = values.last
if match_data = value.match(YYYY_MM_DD_REGEXP)
Time.zone.parse(
"#{match_data[:year].to_i}-#{match_data[:month].to_i}-#{match_data[:day].to_i}",
)
end
when "likes-min", "likes-max", "likes-op-min", "likes-op-max", "posts-min", "posts-max",
"posters-min", "posters-max", "views-min", "views-max"
value = values.last
@@ -117,6 +142,18 @@ class TopicsFilter
end
end
def filter_by_activity(before: nil, after: nil)
filter_by_topic_range(column_name: "topics.bumped_at", min: after, max: before)
end
def filter_by_created(before: nil, after: nil)
filter_by_topic_range(column_name: "topics.created_at", min: after, max: before)
end
def filter_by_latest_post(before: nil, after: nil)
filter_by_topic_range(column_name: "topics.last_posted_at", min: after, max: before)
end
def filter_by_number_of_posts(min: nil, max: nil)
filter_by_topic_range(column_name: "topics.posts_count", min:, max:)
end