module ALD::API::Conditioned

used by Collection classes to work with special conditions in #where.

Requires @conditions to be the instance's condition Hash.

Public

↑ top

Public Instance Methods

where(conditions) click to toggle source

Filter the Collection's data. See the documentation on the individual classes for more information.

# File lib/ALD/conditioned.rb, line 11
def where(conditions)
  return self if conditions.nil? || conditions.empty?
  new_conditions = merge_conditions(conditions)

  if initialized? && Collection::LocalFilter.can_apply?(conditions, self.class::LOCAL_CONDITIONS)
    self.class::new(
      @api,
      new_conditions,
      Collection::LocalFilter.apply_conditions(@data, conditions)
    )
  else
    self.class::new(@api, new_conditions)
  end
end

Internal

↑ top

Constants

RANGE_REGEX

A regex to determine if a range condition is specifying a range.

Private Instance Methods

array_queries(conds) click to toggle source

The HTTP query conditions for queries for an array of values for the given conditions.

conds

an Array of Strings, containing the condition names to handle

Returns

Returns a Hash with the query parameters matching the instance's values on the specified conditions, or an empty Hash.

# File lib/ALD/conditioned.rb, line 74
def array_queries(conds)
  Hash[
    present_conditions(conds).map { |cond| [cond, @conditions[cond.to_sym].join(',')] }
  ]
end
exact_queries(conds) click to toggle source

The HTTP query conditions for exact queries for a set of given conditions.

conds

an Array of Strings, containing the condition names to handle

Returns

Returns a Hash with the query parameters matching the instance's values on the specified conditions, or an empty Hash, if there are none.

# File lib/ALD/conditioned.rb, line 61
def exact_queries(conds)
  Hash[
    present_conditions(conds).map { |cond| [cond, @conditions[cond.to_sym]] }
  ]
end
merge_conditions(conditions) click to toggle source

Merge new conditions with the current ones.

conditions

the new condition Hash to merge

Returns

Returns the merged Hash

Raises ArgumentError if the conditions are incompatible

# File lib/ALD/conditioned.rb, line 134
def merge_conditions(conditions)
  @conditions.merge(conditions) do |key, old_value, new_value|
    if self.class::RANGE_CONDITIONS.include?(key.to_s)
      merge_ranges(key, old_value, new_value) # handle merging for cases like 'downloads >= 5' and 'downloads <= 9' etc.
    elsif self.class::ARRAY_CONDITIONS.include?(key.to_s)
      old_value + new_value
    elsif key == :range # not a "range condition" in the sense used above
      range_offset(new_value)
    elsif key == :sort
      new_value # enable re-sorting
    else
      raise ArgumentError # for other overwrites fail!
    end
  end
end
merge_ranges(key, old, new) click to toggle source

Handle condition conflicts for range conditions. Used by #where.

key

the Symbol key whose range is merged

old

the old range condition value

new

the new range condition value to be applied on top of the old one

Returns

Returns the value that should be used in the merged conditions.

Raises ArgumentError if the conflict cannot be resolved.

# File lib/ALD/conditioned.rb, line 162
def merge_ranges(key, old, new)
  constraints = [new, old]
  data = constraints.map do |c|
    match = RANGE_REGEX.match(c)
    if match.nil?
      [nil, c]
    elsif key == :version
      [match[1], Semantic::Version.new(match[2])]
    else
      [match[1], match[2]]
    end
  end
  ops, values = data.map(&:first), data.map(&:last)

  if ops[0] != ops[1] # one min, one max OR one min/max, one exact
    constraints # => keep both

  elsif ops.none?(&:'nil?') # two range constraints of same type
    ops[0] == '>=' ? ">= #{values.max.to_s}" : "<= #{values.min.to_s}"

  else # two exact values
    if constraints[0].strip == constraints[1].strip # if both are the same, just keep one
      constraints[0]
    else # otherwise this can't be good - throw an error
      raise ArgumentError
    end
  end
end
present_conditions(conds) click to toggle source

Get the subset of conditions that are present on the instance

conds

an Array of Strings, containing the condition names to check

Returns

Returns an Array of Strings with a subset of the given conds, namely those that are present on @conditions.

# File lib/ALD/conditioned.rb, line 123
def present_conditions(conds)
  conds.select { |cond| @conditions.key?(cond.to_sym) }
end
range_condition_queries(conds) click to toggle source

The HTTP query conditions for queries with conditions that allow specifying a range of values.

conds

an Array of Strings, containing the condition names to handle

Returns

Returns a Hash with the query parameters matching the instance's values on the specified conditions, or an empty Hash.

# File lib/ALD/conditioned.rb, line 101
def range_condition_queries(conds)
  Hash[
    present_conditions(conds).map { |cond|
      fields = @conditions[cond.to_sym].is_a?(Array) ? @conditions[cond.to_sym] : [@conditions[cond.to_sym]]
      fields.map do |field|
        match = RANGE_REGEX.match(field)
        if match.nil? # just a specific field
          [cond, field]
        else # min or max
          ["#{cond}-#{match[1] == '>=' ? 'min' : 'max'}", match[2]]
        end
      end
    }.flatten(1)
  ]
end
range_offset(new_range) click to toggle source

Compute an absolute Range from a given relative Range. As ranges specified in #where are relative to this collection, they must be transformed to absolute ranges before being passed to ::new.

new_range

the relative Range to transform

Returns

Returns the absolute Range.

Raises ArgumentError if the relative Range does not fit into this collection's Range.

# File lib/ALD/conditioned.rb, line 201
def range_offset(new_range)
  if @conditions[:range].nil?
    min, max = 0, Float::Infinity
  else
    min, max = @conditions[:range].min, @conditions[:range].max
  end

  new_min = min + new_range.min
  new_max = new_min + new_range.max - new_range.min # == new_min + new_range.size - 1
  raise ArgumentError if new_min > max || new_max > max

  (new_min..new_max)
end
range_query() click to toggle source

The HTTP query conditions for the range specified in the instance's conditions.

Returns

Returns a Hash, that contains the query parameters matching the range specified in the conditions, or an empty Hash if there is no range specified.

# File lib/ALD/conditioned.rb, line 34
def range_query
  data = {}
  if @conditions.key?(:range)
    data['start'] = @conditions[:range].min
    data['count'] = @conditions[:range].max - @conditions[:range].min + 1
  end
  data
end
sort_query() click to toggle source

The HTTP query conditions for the sorting specified in the instance's conditions.

Returns

Returns a Hash containing the query parameters matching the specified sorting, or an empty Hash if there's no sorting specified.

# File lib/ALD/conditioned.rb, line 48
def sort_query
  Hash[
    present_conditions(%w[sort]).map { |cond| [cond, @conditions[cond.to_sym].map { |k, dir| "#{dir == :desc ? '-' : ''}#{k}" }.join(',')] }
  ]
end
switch_queries(conds) click to toggle source

The HTTP query conditions for queries with conditions that can be switched on, off or indeterminate.

conds

an Array of Strings, containing the condition names to handle

Returns

Returns a Hash with the query parameters matching the instance's values on the specified conditions, or an empty Hash.

# File lib/ALD/conditioned.rb, line 87
def switch_queries(conds)
  map = {true => 'true', false => 'false', nil => 'both'}
  Hash[
    present_conditions(conds).map { |cond| [cond, map[@conditions[cond.to_sym]]] }
  ]
end