class ActiveRecord::HierarchicalQuery::Orderings

Constants

NATURAL_SORT_TYPES

Attributes

order_values[R]
table[R]

Public Class Methods

new(order_values, table) click to toggle source

@param [Array] order_values @param [Arel::Table] table

# File lib/active_record/hierarchical_query/orderings.rb, line 16
def initialize(order_values, table)
  @order_values, @table = order_values, table
  @values = nil # cached orderings
end

Public Instance Methods

each(&block) click to toggle source
# File lib/active_record/hierarchical_query/orderings.rb, line 21
def each(&block)
  return @values.each(&block) if @values
  return enum_for(__method__) unless block_given?

  @values = []

  order_values.each do |value|
    Array.wrap(as_orderings(value)).each do |ordering|
      @values << ordering
    end
  end

  @values.each(&block)
end
row_number_expression() click to toggle source

Returns order expression to be inserted into SELECT clauses of both non-recursive and recursive terms.

@return [Arel::Nodes::Node] order expression

# File lib/active_record/hierarchical_query/orderings.rb, line 40
def row_number_expression
  if raw_ordering?
    order_attribute
  else
    Arel.sql("ROW_NUMBER() OVER (ORDER BY #{map(&:to_sql).join(', ')})")
  end
end

Private Instance Methods

as_orderings(value) click to toggle source
# File lib/active_record/hierarchical_query/orderings.rb, line 49
def as_orderings(value)
  case value
    when Arel::Nodes::Ordering
      value

    when Arel::Nodes::Node, Arel::Attributes::Attribute
      value.asc

    when Symbol
      table[value].asc

    when Hash
      value.map { |field, dir| table[field].send(dir) }

    when String
      value.split(',').map do |expr|
        string_as_ordering(expr)
      end

    else
      raise 'Unknown expression in ORDER BY SIBLINGS clause'
  end
end
order_attribute() click to toggle source
# File lib/active_record/hierarchical_query/orderings.rb, line 94
def order_attribute
  first.expr
end
order_column() click to toggle source
# File lib/active_record/hierarchical_query/orderings.rb, line 98
def order_column
  table = order_attribute.relation

  engine = table.class.engine
  if engine == ActiveRecord::Base
    columns =
      if engine.connection.respond_to?(:schema_cache)
        engine.connection.schema_cache.columns_hash(table.name)
      else
        engine.connection_pool.columns_hash[table.name]
      end
  else
    columns = engine.columns_hash
  end

  columns[order_attribute.name.to_s]
end
ordered_by_attribute?() click to toggle source
# File lib/active_record/hierarchical_query/orderings.rb, line 90
def ordered_by_attribute?
  one? && first.ascending? && order_attribute.is_a?(Arel::Attributes::Attribute)
end
raw_ordering?() click to toggle source
# File lib/active_record/hierarchical_query/orderings.rb, line 84
def raw_ordering?
  ordered_by_attribute? &&
      (column = order_column) &&
      NATURAL_SORT_TYPES.include?(column.type)
end
string_as_ordering(expr) click to toggle source
# File lib/active_record/hierarchical_query/orderings.rb, line 73
def string_as_ordering(expr)
  expr.strip!

  if expr.gsub!(/\bdesc\z/i, '')
    Arel.sql(expr).desc
  else
    expr.gsub!(/\basc\z/i, '')
    Arel.sql(expr).asc
  end
end