DEV: Introduce in:pinned filter for experimental /filter route (#20974)

This commit adds support for the `in:pinned` filter to the topics filtering
query language. When the filter is present, it will filter for topics
where `Topic#pinned_until` is greater than `Topic#pinned_at`.
This commit is contained in:
Alan Guo Xiang Tan 2023-04-06 10:13:02 +08:00 committed by GitHub
parent 838fb37019
commit ab54a616c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 0 deletions

View File

@ -14,6 +14,8 @@ class TopicsFilter
/(?<key_prefix>[-=])?(?<key>\w+):(?<value>[^\s]+)/,
) do |key_prefix, key, value|
case key
when "in"
@scope = filter_state(state: value)
when "status"
@scope = filter_status(status: value)
when "tags"
@ -84,6 +86,18 @@ class TopicsFilter
private
def filter_state(state:)
case state
when "pinned"
@scope.where(
"topics.pinned_at IS NOT NULL AND topics.pinned_until > topics.pinned_at AND ? < topics.pinned_until",
Time.zone.now,
)
else
@scope
end
end
def filter_categories(category_slugs:, exclude_subcategories: false, or_clause: false)
category_ids = Category.ids_from_slugs(category_slugs)

View File

@ -24,6 +24,40 @@ RSpec.describe TopicsFilter do
end
end
describe "when filtering with the `in` filter" do
fab!(:topic) { Fabricate(:topic) }
fab!(:pinned_topic) do
Fabricate(:topic, pinned_at: Time.zone.now, pinned_until: 1.hour.from_now)
end
fab!(:expired_pinned_topic) do
Fabricate(:topic, pinned_at: 2.hour.ago, pinned_until: 1.hour.ago)
end
describe "when query string is `in:pinned`" do
it "should return topics that are pinned" do
expect(
TopicsFilter
.new(guardian: Guardian.new)
.filter_from_query_string("in:pinned")
.pluck(:id),
).to contain_exactly(pinned_topic.id)
end
it "should not return pinned topics that have expired" do
freeze_time(2.hours.from_now) do
expect(
TopicsFilter
.new(guardian: Guardian.new)
.filter_from_query_string("in:pinned")
.pluck(:id),
).to eq([])
end
end
end
end
describe "when filtering by categories" do
fab!(:category) { Fabricate(:category, name: "category") }