module Jennifer module QueryBuilder module Ordering # Allow to specify an order by splatted named tuple. # # ``` # Contact.all.order(name: :asc) # ``` def order(**opts) opts.each do |k, v| expression = @expression.c(k.to_s).asc expression.direction = v _order! << expression end self end # Allow to specify an order by hash with string keys. # # ``` # Contact.all.order({"name" => :asc}) # ``` def order(opts : Hash(String, String | Symbol)) opts.each do |k, v| expression = @expression.sql(k.to_s, false).asc expression.direction = v _order! << expression end self end # Allow to specify an order by hash with symbol keys. # # ``` # Contact.all.order({:name => :asc}) # ``` def order(opts : Hash(Symbol, String | Symbol)) opts.each do |k, v| expression = @expression.c(k.to_s).asc expression.direction = v _order! << expression end self end # Allow to specify an order by *OrderExpression*. # # ``` # Contact.all.order(Contact._name.asc) # ``` def order(opt : OrderExpression) _order! << opt self end # Allow to specify an order by *OrderExpression* array. # # ``` # Contact.all.order([Contact._name.asc]) # ``` def order(opts : Array(OrderExpression)) opts.each { |opt| _order! << opt } self end def order(opts : Hash(String | Symbol, String | Symbol)) opts.each do |k, v| field = k.is_a?(String) ? @expression.sql(k, false) : @expression.c(k.to_s) expression = field.asc expression.direction = v _order! << expression end self end # Allow to specify an order passing a block. # # ``` # Contact.all.order { _name.asc } # Contact.all.order { [_name.asc, _age.desc] } # ``` # # Specified block should return `OrderExpression | Array(OrderExpression)`. # To convert `Criteria` or `RawSql` to order item call `#asc` or `#desc`. def order(&block) order(with @expression yield @expression) end # Replace an existing order with the newly specified. # # ``` # Contact.all.order(name: :asc).reorder(age: :desc) # ORDER BY contacts.age DESC # ``` def reorder(**opts) @order = nil order(**opts) end def reorder(opts : Hash(String, String | Symbol)) @order = nil order(opts) end def reorder(opts : Hash(Symbol, String | Symbol)) @order = nil order(opts) end def reorder(opt : OrderExpression) @order = nil order(opt) end def reorder(opts : Array(OrderExpression)) @order = nil order(opts) end def reorder(opts : Hash(String | Symbol, String | Symbol)) @order = nil order(opts) end def reorder(&block) reorder(with @expression yield @expression) end # Show whether order is specified. def ordered? !!_order? end private def reverse_order if _order? _order!.each(&.reverse) else _order! << @expression.c("id").desc end end end end end