app/models/concerns/katalyst/tables/collection/sorting.rb in katalyst-tables-3.0.0.beta1 vs app/models/concerns/katalyst/tables/collection/sorting.rb in katalyst-tables-3.1.0
- old
+ new
@@ -12,48 +12,116 @@
#
# If `sort` is present in params it will override the default sorting.
module Sorting
extend ActiveSupport::Concern
- included do
- config_accessor :sorting
- attr_accessor :sorting
+ DIRECTIONS = %w[asc desc].freeze
+ module SortParams
+ refine Hash do
+ def to_param
+ "#{self[:column]} #{self[:direction]}"
+ end
+ end
+
+ refine String do
+ def to_param
+ to_h.to_param
+ end
+
+ def to_h
+ column, direction = split(/[ +]/, 2)
+
+ direction = "asc" unless DIRECTIONS.include?(direction)
+ { column:, direction: }
+ end
+ end
+ end
+
+ using SortParams
+
+ included do
attribute :sort, :string
+
+ attr_reader :default_sort
end
- def initialize(sorting: config.sorting, **options)
- @sorting = SortForm.parse(sorting, default: sorting) if sorting
+ def initialize(sorting: config.sorting, **)
+ @default_sort = sorting.to_param if sorting.present?
- super(sort: @sorting.to_param, **options) # set default sort based on config
+ super(sort: @default_sort, **) # set default sort based on config
end
+ def default_sort?
+ sort == @default_sort
+ end
+
+ # Returns true if the collection supports sorting on the given column.
+ # A column supports sorting if it is a database column or if
+ # the collection responds to `order_by_#{column}(direction)`.
+ #
+ # @param column [String, Symbol]
+ # @return [true, false]
+ def sortable?(column = nil)
+ if column.nil?
+ @default_sort.present?
+ else
+ items.respond_to?(:"order_by_#{column}") || items.model.has_attribute?(column.to_s)
+ end
+ end
+
+ # Set the current sort behaviour of the collection.
+ #
+ # @param value [String, Hash] "column direction", or { column:, direction: }
def sort=(value)
- return unless @sorting
+ super(value.to_param) if @default_sort
+ end
- # update internal proxy
- @sorting = SortForm.parse(value, default: @sorting.default)
+ # Returns the current sort behaviour of the given column, for use as a
+ # column heading class in the table view.
+ #
+ # @param column [String, Symbol] the table column as defined in table_with
+ # @return [String] the current sort behaviour of the given column
+ def sort_status(column)
+ current, direction = sort.to_h.values_at(:column, :direction)
+ direction if column.to_s == current
+ end
- # update attribute based on normalized value
- super(@sorting.to_param)
+ # Calculates the sort parameter to apply when the given column is toggled.
+ #
+ # @param column [String, Symbol]
+ # @return [String]
+ def toggle_sort(column)
+ current, direction = sort.to_h.values_at(:column, :direction)
+
+ return "#{column} asc" unless column.to_s == current
+
+ direction == "asc" ? "#{column} desc" : "#{column} asc"
end
class Sort # :nodoc:
include Backend
def initialize(app)
@app = app
end
+ using SortParams
+
def call(collection)
- @collection = @app.call(collection)
- @collection.sorting, @collection.items = @collection.sorting.apply(@collection.items) if @collection.sorting
- @collection
- end
+ collection = @app.call(collection)
- # pagy shim
- def params
- @collection.attributes
+ column, direction = collection.sort.to_h.values_at(:column, :direction)
+
+ return collection if column.nil?
+
+ if collection.items.respond_to?(:"order_by_#{column}")
+ collection.items = collection.items.reorder(nil).public_send(:"order_by_#{column}", direction.to_sym)
+ elsif collection.items.model.has_attribute?(column)
+ collection.items = collection.items.reorder(column => direction)
+ end
+
+ collection
end
end
end
end
end