From 2574d61593df31130de8ab8081c7f64038df8db4 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Wed, 10 Sep 2025 17:14:08 +0200 Subject: search: Add a 'kind' parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way you can also filter by the kind of resource you want to be given on the searches page. Signed-off-by: Miquel Sabaté Solà --- app/models/search.rb | 26 ++++++++++++++++++++++---- test/models/search_test.rb | 14 ++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/app/models/search.rb b/app/models/search.rb index 9886f36..b20aabf 100644 --- a/app/models/search.rb +++ b/app/models/search.rb @@ -23,6 +23,7 @@ class Search < ApplicationRecord # And add everything into the `res` hash with the results. res = find_by_text(plain: parsed[:plain]) + res = filter_by_kind(res:, kind: parsed[:kind]) find_by_tags(res:, tags: parsed[:tag]) end @@ -31,16 +32,19 @@ class Search < ApplicationRecord # Returns a hash which contains the tags that has been specified (`tag`) and # the plain text (`plain`) to check on the different fields. def parse_body - res = { tag: [], plain: [] } + res = { tag: [], plain: [], kind: nil } split_body.each do |part| if part.include?(':') parts = part.split(':', 2) parts[1] = clean_clause(part: parts[1]) - next if parts[0] != 'tag' - - res[parts[0].to_sym] << parts[1] + case parts[0] + when 'tag' + res[parts[0].to_sym] << parts[1] + when 'kind' + res[:kind] = Thing.kinds[parts[1]] + end else res[:plain] << part end @@ -100,6 +104,20 @@ class Search < ApplicationRecord res end + # Filter the given `res[:things]` part with the given `kind`. If `kind` is + # nil, then the same `res` object is returned. + def filter_by_kind(res:, kind:) + return res unless kind + + res[:things] = if res[:things].any? + res[:things].and(Thing.where(kind:)) + else + Thing.where(kind:) + end + + res + end + # Returns a hash which groups into taggable types the results by matching the # given `tags` which their references. It expects `res` to be already # initialized by `find_by_text` (yeah, great design, I know), which is also diff --git a/test/models/search_test.rb b/test/models/search_test.rb index 355beab..84bacab 100644 --- a/test/models/search_test.rb +++ b/test/models/search_test.rb @@ -74,6 +74,20 @@ class SearchTest < ActiveSupport::TestCase assert_empty res[:comments] end + test 'returns everything matching a given kind' do + res = Search.new(body: 'some other kind:"novel"').results + + assert_equal res[:things].map(&:target), [things(:thing1).target] + assert_empty res[:comments] + end + + test 'returns everything matching only the given kind' do + res = Search.new(body: 'kind:"novel"').results + + assert_equal res[:things].map(&:target), [things(:thing1).target] + assert_empty res[:comments] + end + test 'returns an empty result with unknown fields' do res = Search.new(body: 'whatever:"unknown"').results -- cgit v1.2.3