Module: ActiveRecordExtended::Utilities::OrderBy

Instance Method Summary collapse

Instance Method Details

#inline_order_by(arel_node, ordering_args) ⇒ Object



8
9
10
11
12
# File 'lib/active_record_extended/utilities/order_by.rb', line 8

def inline_order_by(arel_node, ordering_args)
  return arel_node unless scope_preprocess_order_args(ordering_args)

  Arel::Nodes::InfixOperation.new("ORDER BY", arel_node, ordering_args)
end

#order_by_expression(order_by) ⇒ Object

Processes “ORDER BY” expressions for supported aggregate functions



23
24
25
26
27
28
29
# File 'lib/active_record_extended/utilities/order_by.rb', line 23

def order_by_expression(order_by)
  return false unless order_by && order_by.presence.present?

  to_ordered_table_path(order_by)
    .tap { |order_args| process_ordering_arguments!(order_args) }
    .tap { |order_args| scope_preprocess_order_args(order_args) }
end

#process_ordering_arguments!(ordering_args) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/active_record_extended/utilities/order_by.rb', line 63

def process_ordering_arguments!(ordering_args)
  ordering_args.flatten!
  ordering_args.compact!
  ordering_args.map! do |arg|
    next to_arel_sql(arg) unless arg.is_a?(Hash) # ActiveRecord will reflect if an argument is a symbol

    arg.each_with_object({}) do |(field, dir), ordering_obj|
      # ActiveRecord will not reflect if the Hash keys are a `Arel::Nodes::SqlLiteral` klass
      ordering_obj[to_arel_sql(field)] = dir.to_s.downcase
    end
  end
end

#scope_preprocess_order_args(ordering_args) ⇒ Object



14
15
16
17
18
19
20
# File 'lib/active_record_extended/utilities/order_by.rb', line 14

def scope_preprocess_order_args(ordering_args)
  return false if ordering_args.blank? || !@scope.respond_to?(:preprocess_order_args, true)

  # Sanitation check / resolver (ActiveRecord::Relation#preprocess_order_args)
  @scope.send(:preprocess_order_args, ordering_args)
  ordering_args
end

#to_ordered_table_path(args) ⇒ Object

Turns a hash into a dot notation path.

Example:

  • Using pre-set directions:

    { products: { position: :asc, id: :desc } }

    #=> [{ “products.position” => :asc, “products.id” => :desc }]

  • Using fallback directions:

    :position

    #=> [=> :asc]



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/active_record_extended/utilities/order_by.rb', line 43

def to_ordered_table_path(args)
  flatten_safely(Array.wrap(args)) do |arg|
    next arg unless arg.is_a?(Hash)

    arg.each_with_object({}) do |(tbl_or_col, obj), new_hash|
      if obj.is_a?(Hash)
        obj.each_pair do |o_key, o_value|
          new_hash["#{tbl_or_col}.#{o_key}"] = o_value
        end
      elsif ActiveRecord::QueryMethods::VALID_DIRECTIONS.include?(obj)
        new_hash[tbl_or_col] = obj
      elsif obj.nil?
        new_hash[tbl_or_col.to_s] = :asc
      else
        new_hash["#{tbl_or_col}.#{obj}"] = :asc
      end
    end
  end
end