Module: RailsStuff::SortScope

Defined in:
lib/rails_stuff/sort_scope.rb

Overview

Provides safe and flexible way to sort collections by user’s input. Uses ‘has_scope` gem.

Supports different input format, and limits requested fields to allowed subset.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.filter_param(val, params, allowed, default = nil) ⇒ Object

Filters value with whitelist of allowed fields to sort by.

rubocop:disable CyclomaticComplexity, PerceivedComplexity, BlockNesting



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rails_stuff/sort_scope.rb', line 51

def filter_param(val, params, allowed, default = nil)
  val ||= default
  unless val == default
    val =
      if val.is_a?(Hash)
        val.each_with_object({}) do |(key, dir), h|
          h[key] = (dir == 'desc' ? :desc : :asc) if allowed.include?(key)
        end
      else
        allowed.include?(val) ? val : default
      end
  end
  if val && !val.is_a?(Hash)
    val = {val => ParamsParser.parse_boolean(params[:sort_desc]) ? :desc : :asc}
  end
  val
end

Instance Method Details

#has_sort_scope(config = {}) ⇒ Object

Setups has_scope to order collection by allowed columns. Sort column is filtered by SortScope.filter_param method. Accepts params:

#### Options

  • ‘by` - array of available fields to sort by,

  • ‘default` - default sort expression,

  • ‘only` - bypassed to `has_scope` to limit actions (default to `:index`).

rubocop:disable ClassVars



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/rails_stuff/sort_scope.rb', line 29

def has_sort_scope(config = {})
  @@_sort_scope_id ||= 0
  default = config[:default] || :id
  allowed = Array.wrap(config[:by]).map(&:to_s)
  only_actions = config.fetch(:only, :index)
  # Counter added into scope name to allow to define multiple scopes in same controller.
  has_scope("sort_#{@@_sort_scope_id += 1}",
    as:           :sort,
    default:      nil,
    allow_blank:  true,
    only:         only_actions,
    type:         :any,
  ) do |c, scope, val|
    scope.order(SortScope.filter_param(val, c.params, allowed, default))
  end
end