Class: ActiveRecord::SortableBy::Field

Inherits:
Object
  • Object
show all
Defined in:
lib/sortable_by.rb

Overview

:nodoc:

Constant Summary collapse

STRING_TYPES =

:nodoc:

%i[string text].freeze

Instance Method Summary collapse

Constructor Details

#initialize(name, as: nil, scope: nil, eager_load: nil, case_sensitive: false) ⇒ Field

Returns a new instance of Field.

Raises:

  • (ArgumentError)


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/sortable_by.rb', line 65

def initialize(name, as: nil, scope: nil, eager_load: nil, case_sensitive: false)
  @cols = Array.wrap(as)
  @eager_load = Array.wrap(eager_load).presence
  @case_sensitive = case_sensitive == true

  # validate custom_scope
  @custom_scope = scope
  raise ArgumentError, "Invalid sortable-by field '#{name}': scope must be a Proc." if @custom_scope && !@custom_scope.is_a?(Proc)

  # normalize cols
  @cols.push name if @cols.empty?
  @cols.each do |col|
    case col
    when String, Symbol, Arel::Attributes::Attribute, Arel::Nodes::Node
      next
    when Proc
      raise ArgumentError, "Invalid sortable-by field '#{name}': proc must accept 2 arguments." unless col.arity == 2
    else
      raise ArgumentError, "Invalid sortable-by field '#{name}': invalid type #{col.class}."
    end
  end
end

Instance Method Details

#order(relation, rank) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/sortable_by.rb', line 88

def order(relation, rank)
  @cols.each do |col|
    case col
    when String, Symbol
      type = relation.columns_hash[col.to_s].type
      col  = relation.arel_table[col]
      col  = col.lower if STRING_TYPES.include?(type) && !@case_sensitive
      relation = relation.order(col.send(rank))
    when Arel::Nodes::Node, Arel::Attributes::Attribute
      relation = relation.order(col.send(rank))
    when Proc
      relation = col.call(relation, rank)
    end
  end

  relation = relation.eager_load(*@eager_load) if @eager_load
  relation = relation.instance_eval(&@custom_scope) if @custom_scope
  relation
end