Skip to content

Commit

Permalink
minor refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
ajb committed Nov 25, 2014
1 parent 44c0941 commit ef9bbb2
Showing 1 changed file with 59 additions and 52 deletions.
111 changes: 59 additions & 52 deletions lib/filterer/base.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module Filterer
class Base

IGNORED_PARAMS = [:page]

attr_accessor :results, :meta, :direction, :sort, :params, :opts
Expand All @@ -17,32 +16,42 @@ class Base
class_attribute :per_page_max
self.per_page_max = 1000

def self.sort_option(key, query_string_or_proc = nil, opts = {})
if query_string_or_proc.is_a?(Hash)
opts, query_string_or_proc = query_string_or_proc.clone, nil
end
class << self
def sort_option(key, query_string_or_proc = nil, opts = {})
if query_string_or_proc.is_a?(Hash)
opts, query_string_or_proc = query_string_or_proc.clone, nil
end

if !query_string_or_proc
if key.is_a?(String)
query_string_or_proc = key
else
raise 'Please provide a query string or a proc.'
if !query_string_or_proc
if key.is_a?(String)
query_string_or_proc = key
else
raise 'Please provide a query string or a proc.'
end
end
end

if key.is_a?(Regexp) && opts[:default]
raise "Default sort option can't have a Regexp key."
if key.is_a?(Regexp) && opts[:default]
raise "Default sort option can't have a Regexp key."
end

if query_string_or_proc.is_a?(Proc) && opts[:tiebreaker]
raise "Tiebreaker can't be a proc."
end

self.sort_options += [{
key: key,
query_string_or_proc: query_string_or_proc,
opts: opts
}]
end

if query_string_or_proc.is_a?(Proc) && opts[:tiebreaker]
raise "Tiebreaker can't be a proc."
def count(params = {}, opts = {})
self.new(params, { chainable: true }.merge(opts)).results.count
end

self.sort_options += [{
key: key,
query_string_or_proc: query_string_or_proc,
opts: opts
}]
def chain(params = {}, opts = {})
self.new(params, { chainable: true }.merge(opts)).results
end
end

def initialize(params = {}, opts = {})
Expand Down Expand Up @@ -72,27 +81,24 @@ def get_per_page

def find_results
@results = opts.delete(:starting_query) || starting_query

# Add params
add_params_to_query

return if @opts[:chainable]

# Order results
order_results

@meta[:total] = @results.unscope(:select).count
@meta[:last_page] = [(@meta[:total].to_f / @meta[:per_page]).ceil, 1].max
@meta[:page] = [@meta[:last_page], @meta[:page]].min

return if @opts[:count_only]
add_meta

# Add custom meta data if we've defined the method
@meta.merge!(self.custom_meta_data) if self.respond_to?(:custom_meta_data)

# Return the paginated results
@results = @results.limit(@meta[:per_page]).offset((@meta[:page] - 1)*@meta[:per_page])
end

def add_meta
@meta[:total] = @results.unscope(:select).count
@meta[:last_page] = [(@meta[:total].to_f / @meta[:per_page]).ceil, 1].max
@meta[:page] = [@meta[:last_page], @meta[:page]].min
end

def add_params_to_query
@params.reject { |k, v| k.in?(IGNORED_PARAMS) }
.select { |k, v| v.present? }
Expand All @@ -108,20 +114,33 @@ def order_results
@sort = (params[:sort] && get_sort_option(params[:sort])) ? params[:sort] : default_sort_param

if !get_sort_option(@sort)
@results = @results.order("#{@results.model.table_name}.id ASC")
@results = @results.order default_sort_sql
elsif get_sort_option(@sort)[:query_string_or_proc].is_a?(String)
@results = @results.order %Q{
#{get_sort_option(@sort)[:query_string_or_proc]}
#{@direction}
#{get_sort_option(@sort)[:opts][:nulls_last] ? 'NULLS LAST' : ''}
#{tiebreaker_sort_string ? ',' + tiebreaker_sort_string : ''}
}.squish
@results = @results.order basic_sort_sql
elsif get_sort_option(@sort)[:query_string_or_proc].is_a?(Proc)
matches = get_sort_option(@sort)[:key].is_a?(Regexp) ? @sort.match(get_sort_option(@sort)[:key]) : nil
@results = get_sort_option(@sort)[:query_string_or_proc].call(@results, matches, self)
apply_sort_proc
end
end

def default_sort_sql
"#{@results.model.table_name}.id ASC"
end

def basic_sort_sql
%{
#{get_sort_option(@sort)[:query_string_or_proc]}
#{@direction}
#{get_sort_option(@sort)[:opts][:nulls_last] ? 'NULLS LAST' : ''}
#{tiebreaker_sort_string ? ',' + tiebreaker_sort_string : ''}
}.squish
end

def apply_sort_proc
sort_key = get_sort_option(@sort)[:key]
matches = sort_key.is_a?(Regexp) && @sort.match(sort_key)
@results = get_sort_option(@sort)[:query_string_or_proc].call(@results, matches, self)
end

def get_sort_option(x)
self.class.sort_options.detect do |sort_option|
if sort_option[:key].is_a?(Regexp)
Expand All @@ -144,20 +163,8 @@ def tiebreaker_sort_string
end.try(:[], :query_string_or_proc)
end


def starting_query
raise 'You must override this method!'
end

def self.count(params = {}, opts = {})
filterer = self.new(params, { count_only: true }.merge(opts))
return filterer.meta[:total]
end

def self.chain(params = {}, opts = {})
filterer = self.new(params, { chainable: true }.merge(opts))
return filterer.results
end

end
end

0 comments on commit ef9bbb2

Please sign in to comment.