Skip to content

Instantly share code, notes, and snippets.

@brycesch
Last active December 22, 2015 20:48
Show Gist options
  • Save brycesch/6528470 to your computer and use it in GitHub Desktop.
Save brycesch/6528470 to your computer and use it in GitHub Desktop.
general purpose search method to be used with the tire gem.
module FilteredSearch
extend ActiveSupport::Concern
module ClassMethods
def filtered_search(conditions, filters = {}, options = {})
return [] unless self.respond_to?(:tire) or conditions.nil?
FilteredSearch::CustomSearch.new(self, conditions, filters, options).search
end
end
class CustomSearch
attr_accessor :index
attr_accessor :conditions
attr_accessor :filters
attr_accessor :options
def initialize(index, conditions, filters, options)
self.index = index
self.conditions = nested_condition(conditions)
self.filters = nested_filter(filters)
self.options = symbolized_copy(options)
self.options[:load] = true unless options.has_key?(:load)
end
def search
# Required declaration since &block only retains local scope
conditions = @conditions
filters = @filters
options = @options
order_criteria = order_by
index.tire.search options do
query do
boolean do
conditions.each do |cond|
should { string cond }
end
end
end
order_criteria.each do |order|
sort { by order.first, order.last}
end
filters.each do |key, value|
filter :term, key => value
end
end
end
def nested_filter(value, key = nil)
return key ? {key => value} : {} unless value.is_a?(Hash)
filters = {}
value.each do |k,v|
filters.merge!(nested_filter(v, nested_key(key, k)))
end
filters
end
def nested_condition(value, key = nil)
conditions = []
if value.is_a?(Hash)
value.each do |k,v|
conditions << nested_condition(v, nested_key(key, k))
end
else
value = [value] unless value.is_a?(Array)
value.each do |v|
conditions << nested_value(key, v)
end
end
conditions.flatten
end
def order_by
return [] unless @options[:order_by]
order_by = @options[:order_by].split(",")
direction = options[:direction] || :desc
direction = direction.to_s == "asc" ? :asc : :desc
order_by.map{|ob| [ob,direction]}
end
def nested_key(old_key, key)
old_key ? "#{old_key}.#{key}" : key
end
def nested_value(key, value)
key ? "#{key}:#{value}" : value
end
def symbolized_copy(old_hash)
return old_hash unless old_hash.is_a?(Hash)
new_hash = {}
old_hash.each do |key, value|
k = key.respond_to?(:to_sym) ? key.to_sym : key
new_hash.merge!(k => symbolized_copy(value))
end
new_hash
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment