search: fix multiple metatag searches not working in some cases.

Bug: in some cases searching for multiple metatags would cause one
metatag to be ignored. For example, a search for {{user:1 pool:2}} would
be treated as a search for {{pool:2}}.

Cause: we used `ActiveRecord::Relation#merge` to combine two relations,
which was wrong because `merge` doesn't combine `column IN (?)` clauses
correctly. If there are two `column IN (?)` clauses on the same column,
then `#merge` takes only the second clause and ignores the first.

Fix: write our own half-baked `#and` method to work around Rails'
broken-by-design `#merge` method.

ref: https://github.com/rails/rails/issues/33501.
This commit is contained in:
evazion
2020-04-27 22:29:42 -05:00
parent 1ccefa613f
commit 8cbcec285d
3 changed files with 21 additions and 8 deletions

View File

@@ -5,6 +5,15 @@ module Searchable
unscoped.where(all.where_clause.invert(kind).ast)
end
# XXX hacky method to AND two relations together.
def and(relation)
q = all
q = q.where(relation.where_clause.ast) if relation.where_clause.present?
q = q.joins(relation.joins_values + q.joins_values) if relation.joins_values.present?
q = q.order(relation.order_values) if relation.order_values.present?
q
end
# `operator` is an Arel::Predications method: :eq, :gt, :lt, :between, :in, etc.
# https://github.com/rails/rails/blob/master/activerecord/lib/arel/predications.rb
def where_operator(field, operator, *args)

View File

@@ -117,7 +117,7 @@ class PostQueryBuilder
def metatags_match(metatags, relation)
metatags.each do |metatag|
relation = relation.merge(metatag_matches(metatag.name, metatag.value, quoted: metatag.quoted))
relation = relation.and(metatag_matches(metatag.name, metatag.value, quoted: metatag.quoted))
end
relation