lib/trailblazer/finder/features/sorting.rb in trailblazer-finder-0.1.2 vs lib/trailblazer/finder/features/sorting.rb in trailblazer-finder-0.1.3
- old
+ new
@@ -3,58 +3,100 @@
module Features
module Sorting
def self.included(base)
base.extend ClassMethods
base.instance_eval do
- filter_by :sort do |entity_type, _|
- sort_it(entity_type, sort_attribute, sort_direction)
+ filter_by :sort do |entity_type, value|
+ next sort_it(entity_type, [sort_orders(sort_attribute(value), sort_direction(value))]) if value.nil?
+ sort_attributes = value.split(',')
+ sorters = []
+ sort_attributes.each do |sort_attr|
+ sorters << sort_orders(sort_attribute(sort_attr), sort_direction(sort_attr))
+ end
+ sort_it(entity_type, sorters)
end
end
end
- # Adapters will overwite this method
- def sort_it(entity_type, sort_attribute, sort_direction)
- case sort_direction
- when 'asc', 'ascending'
- entity_type.sort_by { |a| a[sort_attribute.to_sym] }
- when 'desc', 'descending'
- entity_type.sort_by { |a| a[sort_attribute.to_sym] }.reverse
- end
- end
-
def sort?(attribute)
- attribute == sort || sort.to_s.start_with?("#{attribute} ")
+ sort.include?(attribute.to_s)
end
- def sort_attribute
- @sort_attribute ||= Utils::Extra.ensure_included sort.to_s.split(' ', 2).first, self.class.sort_attributes
+ def sort_direction_for(attribute)
+ return 'asc' if !sort.nil? && sort.include?("#{attribute} asc")
+ 'desc'
end
- def sort_direction
- @sort_direction ||= Utils::Extra.ensure_included sort.to_s.split(' ', 2).last, %w[desc asc]
+ def reverse_sort_direction_for(attribute)
+ return 'desc' if sort_direction_for(attribute) == 'asc'
+ 'asc'
end
- def sort_direction_for(attribute)
- if sort_attribute == attribute.to_s
- reverted_sort_direction
- else
- 'desc'
- end
+ def sort_params_for(attribute, options = {})
+ options['sort'] = if sort.nil?
+ "#{attribute} #{sort_direction_for(attribute)}"
+ elsif sort.include?(attribute.to_s)
+ sort
+ else
+ "#{attribute} #{sort_direction_for(attribute)}"
+ end
+ params options
end
- def sort_params_for(attribute, options = {})
+ def new_sort_params_for(attribute, options = {})
options['sort'] = "#{attribute} #{sort_direction_for(attribute)}"
params options
end
- def reverted_sort_direction
- sort_direction == 'desc' ? 'asc' : 'desc'
+ def add_sort_params_for(attribute, options = {})
+ options['sort'] = if sort.nil?
+ "#{attribute} #{sort_direction_for(attribute)}"
+ elsif sort.include?(attribute.to_s)
+ sort.gsub(/#{attribute} #{sort_direction_for(attribute)}/, "#{attribute} #{reverse_sort_direction_for(attribute)}")
+ else
+ "#{sort}, #{attribute} #{sort_direction_for(attribute)}"
+ end
+ params options
end
+ private
+
+ # ORM Adapters will overwite this method
+ def sort_it(entity_type, sort_attributes)
+ entity_type.sort do |this, that|
+ sort_attributes.reduce(0) do |diff, order|
+ next diff if diff != 0 # this and that have differed at an earlier order entry
+ key, direction = order
+ # deal with nil cases
+ next 0 if this[key].nil? && that[key].nil?
+ next 1 if this[key].nil?
+ next -1 if that[key].nil?
+ # do the actual comparison
+ comparison = this[key] <=> that[key]
+ comparison * direction
+ end
+ end
+ end
+
+ # ORM Adapters will overwite this method
+ def sort_orders(sort_attr, sort_dir)
+ [sort_attr.to_sym, (sort_dir.to_sym == :asc ? 1 : -1)]
+ end
+
+ def sort_attribute(attribute)
+ result = Utils::Extra.ensure_included attribute.to_s.split(' ', 2).first, self.class.sort_attributes
+ result
+ end
+
+ def sort_direction(attribute)
+ return Utils::Extra.ensure_included attribute.to_s.split(' ', 2).last, %w[desc asc] unless attribute.nil?
+ 'desc'
+ end
+
module ClassMethods
+ attr_accessor :sorted_attributes
def sortable_by(*attributes)
- config[:sort_attributes] = attributes.map(&:to_s)
- config[:defaults]['sort'] = "#{config[:sort_attributes].first} desc"
+ config[:sort_attributes] = attributes.map(&:to_s)
end
def sort_attributes
config[:sort_attributes] ||= []
end