Class: OrderQuery::Column

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

Overview

An order column (sort column)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope, attr_name, *vals_and_or_dir, unique: nil, nulls: false, sql: nil) ⇒ Column

Returns a new instance of Column.

Parameters:

  • scope (ActiveRecord::Relation)
  • attr_name (Symbol)

    the name of the column, or the method providing the value to sort by.

  • vals_and_or_dir (Array)

    optionally, values in the desired order, and / or one of ‘:asc`, `:desc`. Default order is `:desc` if the values are given (so the result is ordered like the values), `:asc` otherwise.

  • unique (Boolean) (defaults to: nil)

    mark the attribute as unique to avoid redundant columns. Default: ‘true` for primary key.

  • nulls (:first, :last, false) (defaults to: false)

    whether to consider NULLS to be ordered first or last. If false, assumes that a column is not nullable and raises [Errors::NonNullableColumnIsNullError] if a null is encountered.

  • sql (String, nil) (defaults to: nil)

    a custom sql fragment.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/order_query/column.rb', line 29

def initialize(scope, attr_name, *vals_and_or_dir,
               unique: nil, nulls: false, sql: nil)
  @name = attr_name
  @order_enum = vals_and_or_dir.shift if vals_and_or_dir[0].is_a?(Array)
  @direction = Direction.parse!(
    vals_and_or_dir.shift || (@order_enum ? :desc : :asc)
  )
  unless vals_and_or_dir.empty?
    fail ArgumentError,
         "extra arguments: #{vals_and_or_dir.map(&:inspect) * ', '}"
  end
  @unique = unique.nil? ? (name.to_s == scope.primary_key) : unique
  if @order_enum && (@order_enum[0].nil? || @order_enum[-1].nil?)
    fail ArgumentError, '`nulls` cannot be set if a value is null' if nulls
    @nullable = true
    @nulls = if @order_enum[0].nil?
               @direction == :desc ? :first : :last
             else
               @direction == :desc ? :last : :first
             end
  else
    @nullable = !!nulls # rubocop:disable Style/DoubleNegation
    @nulls = NullsDirection.parse!(
      nulls || NullsDirection.default(scope, @direction)
    )
  end
  @custom_sql = sql
  @sql_builder = SQL::Column.new(scope, self)
end

Instance Attribute Details

#custom_sqlObject (readonly)

Returns the value of attribute custom_sql.



9
10
11
# File 'lib/order_query/column.rb', line 9

def custom_sql
  @custom_sql
end

#nameObject (readonly)

Returns the value of attribute name.



9
10
11
# File 'lib/order_query/column.rb', line 9

def name
  @name
end

#order_enumObject (readonly)

Returns the value of attribute order_enum.



9
10
11
# File 'lib/order_query/column.rb', line 9

def order_enum
  @order_enum
end

Instance Method Details

#default_nulls_direction(reverse = false) ⇒ :first, :last

Returns:

  • (:first, :last)


72
73
74
# File 'lib/order_query/column.rb', line 72

def default_nulls_direction(reverse = false)
  NullsDirection.default(scope, direction(reverse))
end

#direction(reverse = false) ⇒ Object

rubocop:enable Metrics/ParameterLists,Metrics/AbcSize rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity rubocop:enable Metrics/MethodLength



62
63
64
# File 'lib/order_query/column.rb', line 62

def direction(reverse = false)
  reverse ? Direction.reverse(@direction) : @direction
end

#enum_side(value, side, strict = true) ⇒ Array

Returns valid order values before / after the given value.

Examples:

for [:difficulty, [‘Easy’, ‘Normal’, ‘Hard’]]:

enum_side('Normal', :after) #=> ['Hard']
enum_side('Normal', :after, false) #=> ['Normal', 'Hard']

Parameters:

  • value (Object)
  • side (:before, :after)

Returns:

  • (Array)

    valid order values before / after the given value.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/order_query/column.rb', line 90

def enum_side(value, side, strict = true)
  ord = order_enum
  pos = ord.index(value)
  if pos
    dir = direction
    if side == :after && dir == :desc || side == :before && dir == :asc
      ord.from pos + (strict ? 1 : 0)
    else
      ord.first pos + (strict ? 0 : 1)
    end
  else
    # default to all if current is not in sort order values
    []
  end
end

#inspectObject



106
107
108
109
110
111
112
113
114
115
# File 'lib/order_query/column.rb', line 106

def inspect
  parts = [
    @name,
    (@order_enum.inspect if order_enum),
    ('unique' if @unique),
    (column_name if @custom_sql),
    @direction
  ].compact
  "(#{parts.join(' ')})"
end

#nullable?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/order_query/column.rb', line 76

def nullable?
  @nullable
end

#nulls_direction(reverse = false) ⇒ :first, :last

Returns:

  • (:first, :last)


67
68
69
# File 'lib/order_query/column.rb', line 67

def nulls_direction(reverse = false)
  reverse ? NullsDirection.reverse(@nulls) : @nulls
end

#unique?Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/order_query/column.rb', line 80

def unique?
  @unique
end