msfl 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 51e5ed15234f2119cf9a96d709f7cb15505f6e75
4
- data.tar.gz: b31ccaeae664a0d09c359322875a892d55808e71
3
+ metadata.gz: 8b2132d5eaec0ac5b4a2055174d6f40685580f40
4
+ data.tar.gz: 0ff98ee3c34b4225a43c8e9433b0c08b87e2521f
5
5
  SHA512:
6
- metadata.gz: 6b8cdc31ca60efdbb600107dfd98c10580eac574c3677c2a24b34fdbf7933de5c488d719340a3a8d048c9b4be520b06ad456df80f7413c803f8cae607f24c391
7
- data.tar.gz: 1a41e178d9b1230eeb16503b4411bc85a6daebc8260df764aea726c7880ee1fb11f608e316654bbfc64a433b46ee4e1675dfb2d15b114cd97d903f1a13258ab9
6
+ metadata.gz: cdacb790d452b5343363f7b8e420f4a37aabd3e5e16f2005031545f79389c06f528c42601ef8f537350a993cfce5b1af745b5607142c041af50df784930091ba
7
+ data.tar.gz: 5c429cf64452914f271a8ad7513627e009c1d8ea33c1a5f9768277df9f2c660f62c02615a4823bb434fed98c1c9478383e8337495646b8f93579390cc54f8fd0
@@ -49,22 +49,28 @@ module MSFL
49
49
  def implicit_and_to_explicit_recursively(obj, parent_key = nil)
50
50
  if obj.is_a? Hash
51
51
  first_key = obj.keys.first
52
- if hash_key_operators.include?(first_key)
53
- # the first key an operator
54
- raise ArgumentError, "#implicit_and_to_explicit requires that all or none of a hash's keys be operators" unless all_operators?(obj.keys)
55
- # all keys are operators
56
- raise ArgumentError, "#implicit_and_to_explicit requires that parent_key be specified when converting operators" if parent_key.nil?
57
- # parent key is non nil
58
- and_array = []
59
- obj.each do |k, v|
60
- and_array << { parent_key => { k => implicit_and_to_explicit_recursively(v, k) } }
61
- end
52
+ if binary_operators.include?(first_key)
53
+ result = i_to_e_bin_op obj, parent_key
54
+ elsif logical_operators.include?(first_key)
55
+ result = i_to_e_log_op obj, parent_key
62
56
  else
63
57
  # the first key is not an operator
64
58
  # if there is only one key just assign the result of calling this method recursively on the value to the result for the key
65
59
  if obj.keys.count == 1
66
60
  if obj[first_key].is_a?(Hash)
67
61
  result = implicit_and_to_explicit_recursively obj[first_key], first_key
62
+ elsif obj[first_key].is_a? MSFL::Types::Set
63
+ # This situation occurs when there are nested logical operators
64
+ # obj is a hash, with one key that is not a binary operator which has a value that is a MSFL::Types::Set
65
+ result = { }
66
+ and_array = MSFL::Types::Set.new
67
+ obj[first_key].each do |v|
68
+ # byebug
69
+ and_array << implicit_and_to_explicit_recursively(v)
70
+ end
71
+ result[first_key] = and_array
72
+ elsif obj[first_key].is_a? Array
73
+ 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"
68
74
  end
69
75
  else
70
76
  raise ArgumentError, "#implicit_and_to_explicit requires that all or none of a hash's keys be operators" if any_operators?(obj.keys)
@@ -77,14 +83,11 @@ module MSFL
77
83
  and_array << { k => v }
78
84
  end
79
85
  end
86
+ result = { and: MSFL::Types::Set.new(and_array) }
80
87
  end
81
88
  end
82
- result ||= { and: MSFL::Types::Set.new(and_array) }
83
89
  elsif obj.is_a? MSFL::Types::Set
84
- result = Types::Set.new
85
- obj.each do |v|
86
- result << implicit_and_to_explicit_recursively(v)
87
- end
90
+ result = i_to_e_set obj, parent_key
88
91
  elsif obj.is_a? Array
89
92
  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"
90
93
  end
@@ -92,23 +95,51 @@ module MSFL
92
95
  end
93
96
 
94
97
  private
95
- # Use this method for converting implicit and hashes to explicit ones when the keys are operators
96
- def implicit_to_explicit_for_ops(hash)
97
- and_array = []
98
- field = hash.keys.first
99
- if hash[field].is_a? Hash
100
- hash[field].each do |k, v|
101
- and_array << { field => { k => v } }
98
+ # Recursively handle a hash containing keys that are all logical operators
99
+ def i_to_e_log_op(hash, parent_key = nil)
100
+ raise ArgumentError, "#implicit_and_to_explicit requires that all or none of a hash's keys be logical operators" unless all_logical_operators?(hash.keys)
101
+ result = {}
102
+ hash.each do |key, value|
103
+ result[key] = implicit_and_to_explicit_recursively value
104
+ end
105
+ result
106
+ end
107
+
108
+ # Recursively handle a hash containing keys that are all binary operators
109
+ def i_to_e_bin_op(hash, parent_key = nil)
110
+ # the first key an operator
111
+ raise ArgumentError, "#implicit_and_to_explicit requires that all or none of a hash's keys be operators" unless all_operators?(hash.keys)
112
+ # all keys are operators
113
+
114
+ first_key = hash.keys.first
115
+ if hash.keys.count == 1
116
+ # There's only one key so there cannot be an implied AND at this level
117
+ if parent_key && (! binary_operators.include?(parent_key)) # this needs more testing - I'm not entirely sure if I should check for this esoteric case of immediately nested explicit ANDs inside of an implied AND
118
+ # The parent_key argument was provided which means that the caller expects the result to be a hash of at least two levels
119
+ # where the first level has a key of the parent_key with a value of a hash
120
+ # first_key is passed in the recursive call
121
+ { parent_key => { first_key => implicit_and_to_explicit_recursively(hash[first_key], first_key)}}
122
+ else
123
+ { first_key => implicit_and_to_explicit_recursively(hash[first_key]) }
102
124
  end
125
+
126
+ else
127
+ raise ArgumentError, "#implicit_and_to_explicit requires that parent_key be specified when converting operators" if parent_key.nil?
128
+ # parent key is non nil
129
+ and_array = []
130
+ hash.each do |k, v|
131
+ and_array << { parent_key => { k => implicit_and_to_explicit_recursively(v, k) } }
132
+ end
133
+ { and: MSFL::Types::Set.new(and_array) }
103
134
  end
104
- { and: MSFL::Types::Set.new(and_array) }
105
135
  end
106
136
 
107
- # Use this method for converting implicit and hashes to explicit ones when the keys are properties
108
- def implicit_to_explicit_for_field(hash)
109
- and_array = []
110
- hash.each { |key, value| and_array << { key => value } }
111
- { and: MSFL::Types::Set.new(and_array) }
137
+ def i_to_e_set(set, parent_key = nil)
138
+ result = MSFL::Types::Set.new
139
+ set.each do |v|
140
+ result << implicit_and_to_explicit_recursively(v)
141
+ end
142
+ result
112
143
  end
113
144
  end
114
145
  end
@@ -13,9 +13,11 @@ module MSFL
13
13
 
14
14
  # Operators still needing parsing: ellipsis2, tilda
15
15
  def hash_key_operators
16
+ binary_operators.concat(logical_operators)
17
+ end
18
+
19
+ def binary_operators
16
20
  [
17
- :and, # logical AND
18
- :or, # logical OR
19
21
  :in, # IN
20
22
  :between, # inclusive range for integers, dates, and date times
21
23
  :start, # a range bound inclusively to the left
@@ -31,6 +33,10 @@ module MSFL
31
33
  ]
32
34
  end
33
35
 
36
+ def logical_operators
37
+ [:and, :or]
38
+ end
39
+
34
40
  # Returns true if all elements of arr are operators, false otherwise
35
41
  #
36
42
  # @param arr [Array<Symbol>] the Array of Symbols to be checked against the operators list
@@ -42,6 +48,18 @@ module MSFL
42
48
  true
43
49
  end
44
50
 
51
+
52
+ # Returns true if all elements of arr are logical operators, false otherwise
53
+ #
54
+ # @param arr [Array<Symbol>] and array of symbols to check to see if all elements are logical operators
55
+ # @return [Bool] it is true if all the elements are logical operators, otherwise false
56
+ def all_logical_operators?(arr)
57
+ arr.each do |e|
58
+ return false unless logical_operators.include?(e)
59
+ end
60
+ true
61
+ end
62
+
45
63
  # Returns true if any of the elements in arr are operators, otherwise false
46
64
  #
47
65
  # @param arr [Array] the array of elements to check for the presence of operators
data/msfl.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'msfl'
3
- s.version = '1.1.0'
3
+ s.version = '1.1.1'
4
4
  s.date = '2015-04-01'
5
5
  s.summary = "MSFL in Ruby"
6
6
  s.description = "Serializers, validators, and other tasty goodness for the Mattermark Semantic Filter Language in Ruby."
@@ -12,6 +12,40 @@ describe "MSFL::Converters::Operator" do
12
12
 
13
13
  let(:expected) { raise ArgumentError, "You are expected to define the expected value" }
14
14
 
15
+ context "when there is not an implicit AND" do
16
+
17
+ let(:expected) { arg }
18
+
19
+ context "when the arg is a scalar" do
20
+
21
+ let(:arg) { 50 }
22
+
23
+ it "is the arg unchanged" do
24
+ expect(mut).to eq expected
25
+ end
26
+ end
27
+
28
+ context "when the arg is single level" do
29
+
30
+ let(:arg) { { gte: 1000 } }
31
+
32
+ it "is the arg unchanged" do
33
+ expect(mut).to eq expected
34
+ end
35
+ end
36
+
37
+ context "when the arg is multi level" do
38
+
39
+ let(:arg) { { value: { gte: 1000 } } }
40
+
41
+ it "is the arg unchanged" do
42
+ expect(mut).to eq expected
43
+ end
44
+ end
45
+
46
+
47
+ end
48
+
15
49
  context "when the implicit AND exists on a Hash whose keys are fields" do
16
50
 
17
51
  # TYPE 1 --- { make: "chevy", year: 2010 } => { and: [ { make: "chevy" }, { year: 2010 }] }
@@ -64,6 +98,33 @@ describe "MSFL::Converters::Operator" do
64
98
  end
65
99
  end
66
100
  end
101
+
102
+ context "when the implicit AND is within a MSFL::Types::Set" do
103
+
104
+ let(:arg) do
105
+ { and: MSFL::Types::Set.new([
106
+ { make: "chevy", year: { gte: 2010, lte: 2012 } },
107
+ { value: { gte: 1000 } }
108
+ ])}
109
+ end
110
+
111
+ let(:expected) do
112
+ { and: MSFL::Types::Set.new([
113
+ { and: MSFL::Types::Set.new([
114
+ { make: "chevy" },
115
+ { and: MSFL::Types::Set.new([
116
+ { year: { gte: 2010 } },
117
+ { year: { lte: 2012 } }
118
+ ])}
119
+ ])},
120
+ { value: { gte: 1000 } }
121
+ ])}
122
+ end
123
+
124
+ it "converts all of the implicit ANDs" do
125
+ expect(mut).to eq expected
126
+ end
127
+ end
67
128
  end
68
129
 
69
130
  describe "#between_to_gte_lte_recursively" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msfl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courtland Caldwell