class Postjob::Queue::Search::ScopeBuilder

Constants

DatabaseInfo

This module holds cached database info, to be used by the search functions.

EXTRA_SEARCH_ATTRIBUTES

describes which attributes should be returned in addition to a model's columns.

SCHEMA_NAME

Public Class Methods

build(model:, filter:, attributes:) click to toggle source
# File lib/postjob/queue/search/scope_builder.rb, line 10
def build(model:, filter:, attributes:)
  attributes ||= default_search_attributes(model)

  builder(model).send(:scope, filter: filter, attributes: attributes)
end
new(model:, dynamic_filter:) click to toggle source
# File lib/postjob/queue/search/scope_builder.rb, line 48
def initialize(model:, dynamic_filter:)
  @model      = model
  @table_name = "#{SCHEMA_NAME}.#{model}"
  @column_types = DatabaseInfo.column_types(@table_name)
  @dynamic_filter = dynamic_filter
end

Private Class Methods

builder(model) click to toggle source
# File lib/postjob/queue/search/scope_builder.rb, line 40
def builder(model)
  @builders ||= {}
  @builders[model] ||= new(model: model, dynamic_filter: dynamic_filter(model))
end
default_search_attributes(model) click to toggle source
# File lib/postjob/queue/search/scope_builder.rb, line 28
def default_search_attributes(model)
  DatabaseInfo.table_columns("#{SCHEMA_NAME}.#{model}") + (EXTRA_SEARCH_ATTRIBUTES[model] || [])
end
dynamic_filter(model) click to toggle source

Returns the name of the column used for dynamic filtering.

# File lib/postjob/queue/search/scope_builder.rb, line 33
def dynamic_filter(model)
  case model
  when "postjobs" then "tags"
  else "attributes"
  end
end

Private Instance Methods

apply_filters(scope, filter) click to toggle source

apply the filter hash onto the passed in scope. This matches all filters with a name which is matching a column name against the column values. It matches every other filter value against an entry in the dynamic_filter column.

# File lib/postjob/queue/search/scope_builder.rb, line 69
def apply_filters(scope, filter)
  filter.each_key do |key|
    expect! key => [Symbol, String]
  end

  converted_filters = filter.inject({}) do |hsh, (key, value)|
    matches = convert_filter_value(value, key: key)
    matches = matches.first if matches.length == 1
    hsh.update key => matches
  end

  column_filters, tags_filters = converted_filters.partition { |key, _| !@column_types[key].nil? }

  scope = scope.where(Hash[column_filters]) unless column_filters.empty?
  scope = scope.where(@dynamic_filter => Hash[tags_filters]) unless tags_filters.empty?

  scope
end
convert_filter_value(value, key:) click to toggle source
# File lib/postjob/queue/search/scope_builder.rb, line 88
def convert_filter_value(value, key:)
  value = Array(value)

  case @column_types[key]
  when "bigint"   then value.map { |v| Integer(v) }
  when "integer"  then value.map { |v| Integer(v) }
  when nil        then value.map(&:to_s) + value.grep(/\A-?\d+\z/).map(&:to_i)
  else                 value.map(&:to_s)
  end
end
scope(filter:, attributes:) click to toggle source
# File lib/postjob/queue/search/scope_builder.rb, line 55
def scope(filter:, attributes:)
  expect! filter => [Hash, nil]
  expect! attributes => Array

  # build Scope
  scope = Simple::SQL::Scope.new("SELECT #{attributes.join(", ")} FROM #{@table_name}")
  scope = apply_filters(scope, filter) if filter && !filter.empty?
  scope
end