Class: Collavre::Creatives::Filters::SearchFilter

Inherits:
BaseFilter
  • Object
show all
Defined in:
app/services/collavre/creatives/filters/search_filter.rb

Constant Summary collapse

MAX_SEARCH_WORDS =
5

Instance Method Summary collapse

Methods inherited from BaseFilter

#initialize

Constructor Details

This class inherits a constructor from Collavre::Creatives::Filters::BaseFilter

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


7
8
9
# File 'app/services/collavre/creatives/filters/search_filter.rb', line 7

def active?
  params[:search].present?
end

#matchObject



11
12
13
# File 'app/services/collavre/creatives/filters/search_filter.rb', line 11

def match
  matched_relation&.pluck(:id) || []
end

#matched_relationObject

The matching rows as an ActiveRecord relation (ids not yet materialized), so callers that need to order/window in SQL can wrap it as a subquery instead of plucking the whole match set into Ruby first. Returns nil when the search has no usable terms. Keeps the left_joins(:comments).distinct shape (a creative matches when one comment row satisfies every word together with the description) — an EXISTS rewrite would change that semantics, so it stays a joined+distinct relation.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'app/services/collavre/creatives/filters/search_filter.rb', line 22

def matched_relation
  words = params[:search].to_s.strip.split(/\s+/).first(MAX_SEARCH_WORDS)
  return nil if words.empty?

  # Build AND conditions: each word must appear in description OR comments
  conditions = []
  binds = {}

  words.each_with_index do |word, i|
    key = :"q#{i}"
    binds[key] = "%#{sanitize_like(word.downcase)}%"
    conditions << "(LOWER(creatives.description) LIKE :#{key} ESCAPE '\\' " \
                  "OR LOWER(comments.content) LIKE :#{key} ESCAPE '\\')"
  end

  scope
    .left_joins(:comments)
    .where(conditions.join(" AND "), **binds)
    .distinct
end