Skip to content

Feature: Query preprocessing hook #2

@mlins

Description

@mlins

Problem

Apps often need to transform search queries before they hit FTS - normalizing terms, stripping noise words, or applying domain-specific transformations. Currently this requires wrapping the search() method or preprocessing externally.

Use Case

In a food database:

  • Strip size descriptors: "medium apple" → "apple" (avoid branded "MEDIUM APPLE SAUCE")
  • Normalize terms: "garlic cloves" → "garlic" (USDA doesn't use "cloves")
  • Reorder for USDA conventions: "cream cheese" → "cheese cream"

Proposed API

class Food < ApplicationRecord
  include ActiveRecord::Searchable

  searchable do
    field :description, weight: 2.0
    field :category
    
    # Option 1: Block
    preprocess_query do |query|
      query.gsub(/\b(small|medium|large)\b/i, '').strip
    end
    
    # Option 2: Lambda
    preprocess_query ->(q) { MyNormalizer.normalize(q) }
    
    # Option 3: Method reference
    preprocess_query :normalize_search_query
  end
  
  def self.normalize_search_query(query)
    # custom logic
  end
end

Implementation Notes

This would hook into QueryBuilder#sanitize_query, running the custom preprocessor before the existing sanitization logic:

def sanitize_query(terms)
  terms = terms.to_s
  terms = config.preprocess_query.call(terms) if config.preprocess_query
  terms = remove_invalid_characters(terms)
  # ... rest of sanitization
end

Benefits

  • Clean extension point for domain-specific logic
  • Keeps preprocessing close to the searchable configuration
  • Testable in isolation
  • Doesn't require monkey-patching or wrapper methods

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions