Class: MSFL::Converters::Operator

Inherits:
Object
  • Object
show all
Includes:
Validators::Definitions::HashKey
Defined in:
lib/msfl/converters/operator.rb

Constant Summary collapse

CONVERSIONS =

Order is respected by run_conversions in otherwords run_conversions executes conversions in the order they occur in CONVERSIONS, not in the order in which they are passed into the method

conversion order is context-free

[
    :implicit_between_to_explicit_recursively,
    :between_to_gte_lte_recursively,
    :implicit_and_to_explicit_recursively
]

Instance Method Summary collapse

Methods included from Validators::Definitions::HashKey

#all_logical_operators?, #all_operators?, #any_operators?, #binary_operators, #foreign_operators, #hash_key_operators, #logical_operators, #operator?, #partial_operators, #valid_hash_key?, #valid_hash_keys

Instance Method Details

#between_to_gte_lte_recursively(obj) ⇒ Object

Recursively converts all between operators to equivalent anded gte / lte it currently creates the converted operators into the implied AND format

Parameters:

  • obj (Object)

    the object to recurse through to convert all betweens to gte / ltes

Returns:

  • (Object)

    the object with betweens converted to anded gte / ltes



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/msfl/converters/operator.rb', line 70

def between_to_gte_lte_recursively(obj)
  result = obj
  if obj.is_a? Hash
    obj.each do |k, v|
      if v.is_a?(Hash) && v.has_key?(:between) && v[:between].has_key?(:start) && v[:between].has_key?(:end)
        lower_bound = between_to_gte_lte_recursively v[:between][:start]
        upper_bound = between_to_gte_lte_recursively v[:between][:end]
        result[k] = { gte: lower_bound, lte: upper_bound  }
      else
        result[k] = between_to_gte_lte_recursively v
      end
    end
  elsif obj.is_a? Types::Set
    result = recurse_through_set :between_to_gte_lte_recursively, obj
  elsif obj.is_a? Array
    raise ArgumentError, "#between_to_gte_lte requires that it does not contain any Arrays - its argument should preprocessed by .arrays_to_sets and .convert_keys_to_symbols"
  end
  result
end

#implicit_and_to_explicit_recursively(obj, parent_key = nil) ⇒ Hash

Convert a Hash containing an implict and into an explicit and

TYPE 1 —

{ make: "chevy", year: 2010 }
 =>    { and: [ { make: "chevy" }, { year: 2010 }] }

TYPE 2 —

{ year: { gte: 2010, lte: 2012 } }
 => { and: [ { year: { gte: 2010 } }, { year: { lte: 2012 } } ] }

TYPE 3 —

{ make: "chevy", year: { gte: 2010, lte: 2012 } }
 => { and: [ { make: "chevy" }, { and: [ { year: { gte: 2010 } }, { year: { lte: 2012 } } ] } ] }

Parameters:

  • obj (Object)

    the Hash that is an implicit and

Returns:

  • (Hash)

    the resulting explicit hash



105
106
107
108
109
110
111
112
113
114
# File 'lib/msfl/converters/operator.rb', line 105

def implicit_and_to_explicit_recursively(obj, parent_key = nil)
  if obj.is_a? Hash
    result = i_to_e_rec_hash obj, parent_key
  elsif obj.is_a? MSFL::Types::Set
    result = i_to_e_set obj, parent_key
  elsif obj.is_a? Array
    raise ArgumentError, "#implicit_and_to_explicit requires that it does not contain any Arrays - its argument should preprocessed by .arrays_to_sets and .convert_keys_to_symbols"
  end
  result ||= obj
end

#implicit_between_to_explicit_recursively(obj, parent_key = nil) ⇒ Object

{ year: { start: 2001, end: 2005 } }

=> { year: { between: { start: 2001, end: 2015 } } }


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/msfl/converters/operator.rb', line 40

def implicit_between_to_explicit_recursively(obj, parent_key = nil)
  if parent_key == :between
    # The immediately ancestor key is :between, so don't do anything special with :start and :end
    result = Hash.new
    obj.each do |k, v|
      result[k] = implicit_between_to_explicit_recursively(v)
    end
  elsif obj.is_a? Hash
    # if the hash has two keys :start and :end, nest it inside a between and recurse on the values
    if obj.has_key?(:start) && obj.has_key?(:end)
      result = { between: { start: implicit_between_to_explicit_recursively(obj[:start]), end: implicit_between_to_explicit_recursively(obj[:end]) } }
    else
      result = Hash.new
      obj.each do |k, v|
        result[k] = implicit_between_to_explicit_recursively(v, k)
      end
    end
  elsif obj.is_a? Types::Set
    result = recurse_through_set :implicit_between_to_explicit_recursively, obj
  elsif obj.is_a? Array
    raise ArgumentError, "#implicit_between_to_explicit_recursively requires that it does not contain any Arrays - its argument should preprocessed by .arrays_to_sets and .convert_keys_to_symbols"
  end
  result ||= obj
end

#run_conversions(obj, conversions_to_run = nil) ⇒ Object

Runs conversions on an object It respects the order of CONVERSIONS, not the order of elements in conversions_to_run

Parameters:

  • obj (Object)

    the object to run the conversions on

  • conversions_to_run (Array<Symbol>) (defaults to: nil)

    an array of the conversions that should be run, duplicates are ignored

Returns:

  • (Object)

    the object with the conversions applied



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/msfl/converters/operator.rb', line 23

def run_conversions(obj, conversions_to_run = nil)
  conversions_to_run ||= CONVERSIONS
  unless all_conversions?(conversions_to_run)
    raise ArgumentError, "#run_conversions second argument is optional, if specified it must be an Array of Symbols"
  end
  result = obj
  CONVERSIONS.each do |conv|
    # In the order that items are in CONVERSIONS run all of the conversions_to_run
    result = send(conv, result) if conversions_to_run.include?(conv)
  end
  result
end