81 lines
2.1 KiB
Ruby
81 lines
2.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'active_support'
|
|
require 'squeel'
|
|
require_relative './text_to_tsquery'
|
|
require_relative './text_to_sql_query'
|
|
|
|
module PgSearchable
|
|
extend ActiveSupport::Concern
|
|
|
|
included do
|
|
def update_pg_search_cache
|
|
# kept just for compatibility with pg_searchable
|
|
# noop in this implementation
|
|
end
|
|
end
|
|
|
|
class_methods do
|
|
def pg_search(
|
|
fields: [],
|
|
fields_mappings: {},
|
|
cache: nil,
|
|
language: 'english',
|
|
scope: 'scope_search',
|
|
skip_callback: false,
|
|
wildcard: true,
|
|
external_cache_data: nil,
|
|
joins: [],
|
|
default_field: ""
|
|
)
|
|
@ts_search_fields = fields
|
|
@ts_search_fields_mappings = fields_mappings
|
|
@ts_cache_field = cache
|
|
@ts_language = language
|
|
@ts_scope_method = scope
|
|
@ts_skip_cache_update = skip_callback
|
|
@ts_wildcard = wildcard
|
|
@ts_joins = joins
|
|
@default_field = default_field.to_s.empty? ? fields.first : default_field.to_sym
|
|
ts_add_scope
|
|
end
|
|
|
|
def ts_add_scope
|
|
class_eval do
|
|
scope ts_scope_method, ->(value) do
|
|
resulting_ids = ts_search(value).map(&:id)
|
|
where(id: resulting_ids)
|
|
end
|
|
end
|
|
end
|
|
|
|
def ts_search(value)
|
|
return if @ts_search_fields.blank? || value.blank?
|
|
includes(@ts_joins).references(:all).where(
|
|
TextToSqlQuery.new(value, @ts_search_fields, @default_field, @ts_search_fields_mappings).where_clause).distinct
|
|
end
|
|
|
|
def should_update_cache_field?
|
|
!@ts_skip_cache_update && @ts_cache_field.present?
|
|
end
|
|
|
|
def ts_cache_field
|
|
@ts_cache_field
|
|
end
|
|
|
|
def ts_scope_method
|
|
@ts_scope_method
|
|
end
|
|
|
|
def ts_cache_method
|
|
@ts_cache_method
|
|
end
|
|
|
|
def ts_fields_to_vector(extra_data = [])
|
|
field_to_vector = ->(field) { "to_tsvector('#{@ts_language}', coalesce(#{field}::text, ''))" }
|
|
data_to_vector = ->(data) { "to_tsvector('#{@ts_language}', '#{data}')" }
|
|
(@ts_search_fields.map(&field_to_vector) + extra_data.map(&data_to_vector)).join(' || ')
|
|
end
|
|
end
|
|
end
|