class ActiveSet::Sorting::ActiveRecordStrategy

Public Class Methods

new(set, attribute_instructions) click to toggle source
# File lib/active_set/sorting/active_record_strategy.rb, line 8
def initialize(set, attribute_instructions)
  @set = set
  @attribute_instructions = attribute_instructions
  @set_instructions = attribute_instructions.map do |attribute_instruction|
    ActiveRecordSetInstruction.new(attribute_instruction, set)
  end
end

Public Instance Methods

executable_instructions() click to toggle source
# File lib/active_set/sorting/active_record_strategy.rb, line 28
def executable_instructions
  return {} unless @set.respond_to? :to_sql

  @set_instructions.select do |set_instruction|
    attribute_model = set_instruction.attribute_model
    next false unless attribute_model
    next false unless attribute_model.respond_to?(:attribute_names)
    next false unless attribute_model.attribute_names.include?(set_instruction.attribute)

    true
  end
end
execute() click to toggle source
# File lib/active_set/sorting/active_record_strategy.rb, line 16
def execute
  return false unless @set.respond_to? :to_sql

  executable_instructions.reduce(@set) do |set, set_instruction|
    statement = set.merge(set_instruction.initial_relation)
    statement = statement.merge(order_operation_for(set_instruction))

    set_instruction.processed = true
    statement
  end
end

Private Instance Methods

direction_operator(direction) click to toggle source
# File lib/active_set/sorting/active_record_strategy.rb, line 63
def direction_operator(direction)
  return :desc if direction.to_s.downcase.start_with? 'desc'

  :asc
end
nil_sorter_for(model, column, direction) click to toggle source
# File lib/active_set/sorting/active_record_strategy.rb, line 69
def nil_sorter_for(model, column, direction)
  "CASE WHEN #{model.table_name}.#{column} IS NULL #{nil_sorter_then_statement(direction)}"
end
nil_sorter_then_statement(direction) click to toggle source
# File lib/active_set/sorting/active_record_strategy.rb, line 73
def nil_sorter_then_statement(direction)
  first = 'THEN 0 ELSE 1 END'
  last = 'THEN 1 ELSE 0 END'
  if ActiveSet.configuration.on_asc_sort_nils_come == :last
    return last if direction == :asc

    return first
  else
    return first if direction == :asc

    return last
  end
end
order_operation_for(set_instruction) click to toggle source

stackoverflow.com/a/44912964/2884386 When ActiveSet.configuration.on_asc_sort_nils_come == :last null values to be sorted as if larger than any non-null value. ASC => [-2, -1, 1, 2, nil] DESC => [nil, 2, 1, -1, -2] Otherwise sort nulls as if smaller than any non-null value. ASC => [nil, -2, -1, 1, 2] DESC => [2, 1, -1, -2, nil]

# File lib/active_set/sorting/active_record_strategy.rb, line 51
def order_operation_for(set_instruction)
  attribute_model = set_instruction.attribute_model

  arel_column = set_instruction.arel_column
  arel_direction = direction_operator(set_instruction.value)

  attribute_model.order(Arel.sql(nil_sorter_for(set_instruction.arel_table,
                                                set_instruction.arel_column_name,
                                                arel_direction)))
                 .order(arel_column.send(arel_direction))
end