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 +4 -4
- data/lib/msfl/converters/operator.rb +59 -28
- data/lib/msfl/validators/definitions/hash_key.rb +20 -2
- data/msfl.gemspec +1 -1
- data/spec/msfl/converters/operator_spec.rb +61 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b2132d5eaec0ac5b4a2055174d6f40685580f40
|
4
|
+
data.tar.gz: 0ff98ee3c34b4225a43c8e9433b0c08b87e2521f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
53
|
-
|
54
|
-
|
55
|
-
|
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 =
|
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
|
-
#
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
@@ -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
|