shiny_json_logic 0.2.16 → 0.3.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/CHANGELOG.md +12 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -5
- data/lib/shiny_json_logic/comparisons/comparable.rb +27 -4
- data/lib/shiny_json_logic/engine.rb +11 -5
- data/lib/shiny_json_logic/numericals/min_max_collection.rb +9 -14
- data/lib/shiny_json_logic/numericals/numerify.rb +5 -5
- data/lib/shiny_json_logic/numericals/with_error_handling.rb +2 -0
- data/lib/shiny_json_logic/operations/addition.rb +5 -23
- data/lib/shiny_json_logic/operations/all.rb +1 -3
- data/lib/shiny_json_logic/operations/and.rb +3 -4
- data/lib/shiny_json_logic/operations/base.rb +13 -31
- data/lib/shiny_json_logic/operations/coalesce.rb +2 -2
- data/lib/shiny_json_logic/operations/concatenation.rb +4 -4
- data/lib/shiny_json_logic/operations/different.rb +2 -17
- data/lib/shiny_json_logic/operations/division.rb +6 -14
- data/lib/shiny_json_logic/operations/double_not.rb +3 -3
- data/lib/shiny_json_logic/operations/equal.rb +2 -16
- data/lib/shiny_json_logic/operations/exists.rb +4 -4
- data/lib/shiny_json_logic/operations/filter.rb +2 -4
- data/lib/shiny_json_logic/operations/greater.rb +2 -17
- data/lib/shiny_json_logic/operations/greater_equal.rb +2 -17
- data/lib/shiny_json_logic/operations/if.rb +5 -16
- data/lib/shiny_json_logic/operations/inclusion.rb +3 -3
- data/lib/shiny_json_logic/operations/iterable/base.rb +31 -61
- data/lib/shiny_json_logic/operations/max.rb +2 -4
- data/lib/shiny_json_logic/operations/merge.rb +3 -3
- data/lib/shiny_json_logic/operations/min.rb +2 -4
- data/lib/shiny_json_logic/operations/missing.rb +10 -10
- data/lib/shiny_json_logic/operations/missing_some.rb +7 -6
- data/lib/shiny_json_logic/operations/modulo.rb +6 -14
- data/lib/shiny_json_logic/operations/none.rb +1 -3
- data/lib/shiny_json_logic/operations/not.rb +2 -2
- data/lib/shiny_json_logic/operations/or.rb +3 -4
- data/lib/shiny_json_logic/operations/preserve.rb +8 -25
- data/lib/shiny_json_logic/operations/product.rb +7 -20
- data/lib/shiny_json_logic/operations/reduce.rb +24 -30
- data/lib/shiny_json_logic/operations/smaller.rb +2 -17
- data/lib/shiny_json_logic/operations/smaller_equal.rb +2 -17
- data/lib/shiny_json_logic/operations/some.rb +1 -3
- data/lib/shiny_json_logic/operations/strict_different.rb +6 -12
- data/lib/shiny_json_logic/operations/strict_equal.rb +6 -12
- data/lib/shiny_json_logic/operations/substring.rb +4 -4
- data/lib/shiny_json_logic/operations/subtraction.rb +7 -20
- data/lib/shiny_json_logic/operations/throw.rb +5 -7
- data/lib/shiny_json_logic/operations/try.rb +2 -3
- data/lib/shiny_json_logic/operations/val.rb +17 -24
- data/lib/shiny_json_logic/operations/var.rb +18 -16
- data/lib/shiny_json_logic/truthy.rb +9 -7
- data/lib/shiny_json_logic/utils/data_hash.rb +18 -0
- data/lib/shiny_json_logic/version.rb +1 -1
- data/lib/shiny_json_logic.rb +0 -2
- metadata +3 -2
|
@@ -5,9 +5,9 @@ require "shiny_json_logic/operations/base"
|
|
|
5
5
|
module ShinyJsonLogic
|
|
6
6
|
module Operations
|
|
7
7
|
class Inclusion < Base
|
|
8
|
-
def
|
|
9
|
-
needle = evaluate(rules.first)
|
|
10
|
-
haystack = evaluate(rules.last)
|
|
8
|
+
def self.execute(rules, scope_stack)
|
|
9
|
+
needle = evaluate(rules.first, scope_stack)
|
|
10
|
+
haystack = evaluate(rules.last, scope_stack)
|
|
11
11
|
haystack.include?(needle)
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -6,93 +6,63 @@ module ShinyJsonLogic
|
|
|
6
6
|
module Operations
|
|
7
7
|
module Iterable
|
|
8
8
|
class Base < Operations::Base
|
|
9
|
-
def
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return handle_nil if dynamic_args?
|
|
13
|
-
return handle_nil unless rules.is_a?(Array)
|
|
14
|
-
|
|
15
|
-
@filter = rules[1]
|
|
16
|
-
return handle_nil if @filter.nil? && self.class.raise_on_nil_filter?
|
|
17
|
-
|
|
18
|
-
collection = rules.any? ? rules[0] : rules
|
|
19
|
-
return handle_nil if collection.nil?
|
|
9
|
+
def self.raise_on_nil_filter!
|
|
10
|
+
@raise_on_nil_filter = true
|
|
11
|
+
end
|
|
20
12
|
|
|
21
|
-
|
|
13
|
+
def self.raise_on_nil_filter?
|
|
14
|
+
@raise_on_nil_filter
|
|
22
15
|
end
|
|
23
16
|
|
|
24
|
-
def call
|
|
25
|
-
|
|
17
|
+
def self.call(rules, scope_stack)
|
|
18
|
+
rules = resolve_rules(rules, scope_stack)
|
|
26
19
|
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
collection, filter = setup_collection(rules, scope_stack)
|
|
21
|
+
|
|
22
|
+
on_before(scope_stack)
|
|
23
|
+
results = collection.each_with_index.each_with_object([]) do |(item, index), acc|
|
|
24
|
+
scope_stack.push({ "index" => index }, index: index)
|
|
25
|
+
scope_stack.push(item, index: index)
|
|
29
26
|
begin
|
|
30
|
-
solved = on_each(item)
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
solved = on_each(item, filter, scope_stack)
|
|
28
|
+
acc << solved
|
|
29
|
+
scope_stack.pop
|
|
30
|
+
scope_stack.pop
|
|
33
31
|
rescue => e
|
|
34
|
-
# Clean up scopes before re-raising
|
|
35
32
|
scope_stack.pop # item scope
|
|
36
33
|
scope_stack.pop # iterator context scope
|
|
37
34
|
raise e
|
|
38
35
|
end
|
|
39
36
|
end
|
|
40
|
-
|
|
41
|
-
on_after(results)
|
|
37
|
+
on_after(results, scope_stack)
|
|
42
38
|
end
|
|
43
39
|
|
|
44
|
-
|
|
40
|
+
def self.setup_collection(rules, scope_stack)
|
|
41
|
+
return handle_nil unless rules.is_a?(Array)
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
filter = rules[1]
|
|
44
|
+
return handle_nil if filter.nil? && raise_on_nil_filter?
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
end
|
|
46
|
+
collection_rule = rules.any? ? rules[0] : rules
|
|
47
|
+
return handle_nil if collection_rule.nil?
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
# This creates the intermediate level for [[1], "index"] access
|
|
55
|
-
scope_stack.push({ "index" => index }, index: index)
|
|
56
|
-
|
|
57
|
-
# Then push the current item
|
|
58
|
-
scope_stack.push(item, index: index)
|
|
49
|
+
collection = Utils::Array.wrap(Engine.call(collection_rule, scope_stack))
|
|
50
|
+
[collection, filter]
|
|
59
51
|
end
|
|
60
52
|
|
|
61
|
-
def
|
|
62
|
-
# Pop the item scope
|
|
63
|
-
scope_stack.pop
|
|
64
|
-
# Pop the iterator context scope
|
|
65
|
-
scope_stack.pop
|
|
66
|
-
end
|
|
53
|
+
def self.on_before(_scope_stack); end
|
|
67
54
|
|
|
68
|
-
def
|
|
55
|
+
def self.on_each(_item, filter, scope_stack)
|
|
56
|
+
Engine.call(filter, scope_stack)
|
|
69
57
|
end
|
|
70
58
|
|
|
71
|
-
def on_after(results)
|
|
59
|
+
def self.on_after(results, _scope_stack)
|
|
72
60
|
results
|
|
73
61
|
end
|
|
74
62
|
|
|
75
|
-
def handle_nil
|
|
63
|
+
def self.handle_nil
|
|
76
64
|
raise Errors::InvalidArguments
|
|
77
65
|
end
|
|
78
|
-
|
|
79
|
-
def setup_collection(collection)
|
|
80
|
-
if collection.nil?
|
|
81
|
-
@collection = []
|
|
82
|
-
else
|
|
83
|
-
@collection = wrap(evaluate(collection))
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def self.raise_on_nil_filter!
|
|
88
|
-
@raise_on_nil_filter = true
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def self.raise_on_nil_filter?
|
|
92
|
-
@raise_on_nil_filter
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
attr_reader :collection, :filter
|
|
96
66
|
end
|
|
97
67
|
end
|
|
98
68
|
end
|
|
@@ -6,10 +6,8 @@ require "shiny_json_logic/numericals/min_max_collection"
|
|
|
6
6
|
module ShinyJsonLogic
|
|
7
7
|
module Operations
|
|
8
8
|
class Max < Base
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def call
|
|
12
|
-
collect_numeric_values.max
|
|
9
|
+
def self.execute(rules, scope_stack)
|
|
10
|
+
Numericals::MinMaxCollection.collect_numeric_values(rules, scope_stack).max
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
end
|
|
@@ -5,9 +5,9 @@ require "shiny_json_logic/operations/base"
|
|
|
5
5
|
module ShinyJsonLogic
|
|
6
6
|
module Operations
|
|
7
7
|
class Merge < Base
|
|
8
|
-
def
|
|
9
|
-
wrap_nil(rules).map do |rule|
|
|
10
|
-
wrap_nil(evaluate(rule))
|
|
8
|
+
def self.execute(rules, scope_stack)
|
|
9
|
+
Utils::Array.wrap_nil(rules).map do |rule|
|
|
10
|
+
Utils::Array.wrap_nil(evaluate(rule, scope_stack))
|
|
11
11
|
end.reduce([], :+)
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -6,10 +6,8 @@ require "shiny_json_logic/numericals/min_max_collection"
|
|
|
6
6
|
module ShinyJsonLogic
|
|
7
7
|
module Operations
|
|
8
8
|
class Min < Base
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def call
|
|
12
|
-
collect_numeric_values.min
|
|
9
|
+
def self.execute(rules, scope_stack)
|
|
10
|
+
Numericals::MinMaxCollection.collect_numeric_values(rules, scope_stack).min
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
end
|
|
@@ -6,25 +6,25 @@ require "shiny_json_logic/operations/base"
|
|
|
6
6
|
module ShinyJsonLogic
|
|
7
7
|
module Operations
|
|
8
8
|
class Missing < Base
|
|
9
|
-
def
|
|
10
|
-
items = wrap_nil(rules)
|
|
9
|
+
def self.execute(rules, scope_stack)
|
|
10
|
+
items = Utils::Array.wrap_nil(rules)
|
|
11
11
|
keys = []
|
|
12
12
|
items.each do |rule|
|
|
13
|
-
evaluated = evaluate(rule)
|
|
14
|
-
keys.concat(wrap_nil(evaluated).map(&:to_s))
|
|
13
|
+
evaluated = evaluate(rule, scope_stack)
|
|
14
|
+
keys.concat(Utils::Array.wrap_nil(evaluated).map(&:to_s))
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
current_data = scope_stack.current
|
|
17
|
+
return keys unless current_data.is_a?(Hash)
|
|
17
18
|
|
|
18
|
-
keys - deep_keys(
|
|
19
|
+
keys - deep_keys(current_data)
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def deep_keys(hash)
|
|
22
|
+
def self.deep_keys(hash)
|
|
24
23
|
return unless hash.is_a?(Hash)
|
|
25
24
|
|
|
26
|
-
hash.keys.map{|key| ([key.to_s] << deep_keys(hash[key])).compact.join(".") }
|
|
25
|
+
hash.keys.map { |key| ([key.to_s] << deep_keys(hash[key])).compact.join(".") }
|
|
27
26
|
end
|
|
27
|
+
private_class_method :deep_keys
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -6,14 +6,15 @@ require "shiny_json_logic/operations/missing"
|
|
|
6
6
|
module ShinyJsonLogic
|
|
7
7
|
module Operations
|
|
8
8
|
class MissingSome < Missing
|
|
9
|
-
def
|
|
10
|
-
min_required = evaluate(rules[0])
|
|
11
|
-
keys = wrap_nil(evaluate(rules[1])).map(&:to_s)
|
|
12
|
-
|
|
9
|
+
def self.execute(rules, scope_stack)
|
|
10
|
+
min_required = evaluate(rules[0], scope_stack)
|
|
11
|
+
keys = Utils::Array.wrap_nil(evaluate(rules[1], scope_stack)).map(&:to_s)
|
|
12
|
+
current_data = scope_stack.current
|
|
13
|
+
return keys unless current_data.is_a?(Hash) && rules.is_a?(Array)
|
|
13
14
|
|
|
14
|
-
data_keys =
|
|
15
|
+
data_keys = current_data.keys.map(&:to_s)
|
|
15
16
|
present = keys & data_keys
|
|
16
|
-
present.size >= min_required ? [] : Missing.
|
|
17
|
+
present.size >= min_required ? [] : Missing.execute(keys, scope_stack)
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
end
|
|
@@ -7,18 +7,19 @@ require "shiny_json_logic/numericals/numerify"
|
|
|
7
7
|
module ShinyJsonLogic
|
|
8
8
|
module Operations
|
|
9
9
|
class Modulo < Base
|
|
10
|
-
|
|
11
|
-
include Numericals::Numerify
|
|
10
|
+
extend Numericals::WithErrorHandling
|
|
12
11
|
|
|
13
|
-
def
|
|
14
|
-
operands = wrap_nil(rules)
|
|
12
|
+
def self.execute(rules, scope_stack)
|
|
13
|
+
operands = Utils::Array.wrap_nil(rules)
|
|
15
14
|
return handle_invalid_args if operands.empty?
|
|
16
15
|
|
|
17
16
|
safe_arithmetic do
|
|
18
17
|
result = nil
|
|
19
18
|
count = 0
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
operands.each do |rule|
|
|
21
|
+
evaluated = evaluate(rule, scope_stack)
|
|
22
|
+
num = Numericals::Numerify.numerify(evaluated)
|
|
22
23
|
count += 1
|
|
23
24
|
result = result.nil? ? num : result.remainder(num)
|
|
24
25
|
end
|
|
@@ -28,15 +29,6 @@ module ShinyJsonLogic
|
|
|
28
29
|
result
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
|
-
|
|
32
|
-
private
|
|
33
|
-
|
|
34
|
-
def each_operand(operands)
|
|
35
|
-
operands.each do |rule|
|
|
36
|
-
evaluated = evaluate(rule)
|
|
37
|
-
yield numerify(evaluated)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
32
|
end
|
|
41
33
|
end
|
|
42
34
|
end
|
|
@@ -6,9 +6,9 @@ require "shiny_json_logic/truthy"
|
|
|
6
6
|
module ShinyJsonLogic
|
|
7
7
|
module Operations
|
|
8
8
|
class Not < Base
|
|
9
|
-
def
|
|
9
|
+
def self.execute(rules, scope_stack)
|
|
10
10
|
value = rules.is_a?(Array) ? rules.first : rules
|
|
11
|
-
!Truthy.call(evaluate(value))
|
|
11
|
+
!Truthy.call(evaluate(value, scope_stack))
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
end
|
|
@@ -7,17 +7,16 @@ require "shiny_json_logic/numericals/with_error_handling"
|
|
|
7
7
|
module ShinyJsonLogic
|
|
8
8
|
module Operations
|
|
9
9
|
class Or < Base
|
|
10
|
-
|
|
10
|
+
extend Numericals::WithErrorHandling
|
|
11
11
|
raise_on_dynamic_args!
|
|
12
12
|
|
|
13
|
-
def
|
|
14
|
-
return handle_invalid_args if dynamic_args?
|
|
13
|
+
def self.execute(rules, scope_stack)
|
|
15
14
|
return handle_invalid_args unless rules.is_a?(Array)
|
|
16
15
|
return false if rules.empty?
|
|
17
16
|
|
|
18
17
|
result = nil
|
|
19
18
|
rules.each do |rule|
|
|
20
|
-
result = evaluate(rule)
|
|
19
|
+
result = evaluate(rule, scope_stack)
|
|
21
20
|
return result if Truthy.call(result)
|
|
22
21
|
end
|
|
23
22
|
result
|
|
@@ -1,37 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "shiny_json_logic/truthy"
|
|
4
|
+
require "shiny_json_logic/operations/iterable/base"
|
|
4
5
|
|
|
5
6
|
module ShinyJsonLogic
|
|
6
7
|
module Operations
|
|
7
8
|
class Preserve < Iterable::Base
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
# Preserve doesn't need the standard iterable setup (filter, collection from rules[0], etc.)
|
|
12
|
-
@rules = rules
|
|
13
|
-
@scope_stack = scope_stack
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
private
|
|
17
|
-
|
|
18
|
-
def on_each(item)
|
|
19
|
-
Engine.call(item, scope_stack)
|
|
20
|
-
end
|
|
9
|
+
def self.call(rules, scope_stack)
|
|
10
|
+
# Preserve doesn't create new scopes - evaluates each item directly
|
|
11
|
+
collection = Utils::Array.wrap(rules)
|
|
21
12
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
results
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Preserve doesn't create new scopes - it just evaluates expressions
|
|
29
|
-
def on_before_each(_item, _index = 0)
|
|
30
|
-
# Don't push to scope stack
|
|
31
|
-
end
|
|
13
|
+
results = collection.each_with_object([]) do |item, acc|
|
|
14
|
+
acc << Engine.call(item, scope_stack)
|
|
15
|
+
end
|
|
32
16
|
|
|
33
|
-
|
|
34
|
-
# Don't pop from scope stack
|
|
17
|
+
results.size == 1 ? results.first : results
|
|
35
18
|
end
|
|
36
19
|
end
|
|
37
20
|
end
|
|
@@ -7,18 +7,20 @@ require "shiny_json_logic/numericals/numerify"
|
|
|
7
7
|
module ShinyJsonLogic
|
|
8
8
|
module Operations
|
|
9
9
|
class Product < Base
|
|
10
|
-
|
|
11
|
-
include Numericals::Numerify
|
|
10
|
+
extend Numericals::WithErrorHandling
|
|
12
11
|
|
|
13
|
-
def
|
|
14
|
-
operands = wrap_nil(rules)
|
|
12
|
+
def self.execute(rules, scope_stack)
|
|
13
|
+
operands = Utils::Array.wrap_nil(rules)
|
|
15
14
|
return 1 if operands.empty?
|
|
16
15
|
|
|
17
16
|
safe_arithmetic do
|
|
18
17
|
result = nil
|
|
19
18
|
count = 0
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
operands.each do |rule|
|
|
21
|
+
evaluated = evaluate(rule, scope_stack)
|
|
22
|
+
num = Numericals::Numerify.numerify(evaluated)
|
|
23
|
+
num = 0 if num.nil?
|
|
22
24
|
return handle_nan if num.nil?
|
|
23
25
|
count += 1
|
|
24
26
|
result = result.nil? ? num.to_f : result * num.to_f
|
|
@@ -29,21 +31,6 @@ module ShinyJsonLogic
|
|
|
29
31
|
result
|
|
30
32
|
end
|
|
31
33
|
end
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
def each_operand(operands)
|
|
36
|
-
operands.each do |rule|
|
|
37
|
-
evaluated = evaluate(rule)
|
|
38
|
-
yield numerify(evaluated)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def numerify(value)
|
|
43
|
-
val = super
|
|
44
|
-
return 0 if val.nil?
|
|
45
|
-
val
|
|
46
|
-
end
|
|
47
34
|
end
|
|
48
35
|
end
|
|
49
36
|
end
|
|
@@ -7,39 +7,33 @@ require "shiny_json_logic/numericals/with_error_handling"
|
|
|
7
7
|
module ShinyJsonLogic
|
|
8
8
|
module Operations
|
|
9
9
|
class Reduce < Iterable::Base
|
|
10
|
-
|
|
10
|
+
extend Numericals::WithErrorHandling
|
|
11
11
|
raise_on_dynamic_args!
|
|
12
12
|
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def on_each(_item)
|
|
36
|
-
self.accumulator = Engine.call(filter, scope_stack)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def on_after(_results)
|
|
40
|
-
safe_arithmetic do
|
|
41
|
-
self.accumulator
|
|
13
|
+
def self.call(rules, scope_stack)
|
|
14
|
+
rules = resolve_rules(rules, scope_stack)
|
|
15
|
+
|
|
16
|
+
collection, filter = setup_collection(rules, scope_stack)
|
|
17
|
+
|
|
18
|
+
# Evaluate initial accumulator (third argument)
|
|
19
|
+
accumulator = Engine.call(rules[2], scope_stack)
|
|
20
|
+
|
|
21
|
+
collection.each_with_index do |item, index|
|
|
22
|
+
scope_stack.push({ "index" => index }, index: index)
|
|
23
|
+
reduce_scope = { "current" => item, "accumulator" => accumulator }
|
|
24
|
+
scope_stack.push(reduce_scope, index: index)
|
|
25
|
+
begin
|
|
26
|
+
accumulator = Engine.call(filter, scope_stack)
|
|
27
|
+
scope_stack.pop
|
|
28
|
+
scope_stack.pop
|
|
29
|
+
rescue => e
|
|
30
|
+
scope_stack.pop
|
|
31
|
+
scope_stack.pop
|
|
32
|
+
raise e
|
|
33
|
+
end
|
|
42
34
|
end
|
|
35
|
+
|
|
36
|
+
safe_arithmetic { accumulator }
|
|
43
37
|
end
|
|
44
38
|
end
|
|
45
39
|
end
|
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "shiny_json_logic/operations/base"
|
|
4
|
-
require "shiny_json_logic/numericals/with_error_handling"
|
|
5
4
|
require "shiny_json_logic/comparisons/comparable"
|
|
6
5
|
|
|
7
6
|
module ShinyJsonLogic
|
|
8
7
|
module Operations
|
|
9
8
|
class Smaller < Base
|
|
10
|
-
include Numericals::WithErrorHandling
|
|
11
|
-
include Comparisons::Comparable
|
|
12
9
|
raise_on_dynamic_args!
|
|
13
10
|
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
operands = wrap_nil(rules)
|
|
17
|
-
return handle_invalid_args if operands.length < 2
|
|
18
|
-
|
|
19
|
-
prev = evaluate(operands[0])
|
|
20
|
-
operands[1..].each do |rule|
|
|
21
|
-
curr = evaluate(rule)
|
|
22
|
-
result = compare(prev, curr)
|
|
23
|
-
return handle_nan if result == :nan
|
|
24
|
-
return false unless result == -1
|
|
25
|
-
prev = curr
|
|
26
|
-
end
|
|
27
|
-
true
|
|
11
|
+
def self.execute(rules, scope_stack)
|
|
12
|
+
Comparisons::Comparable.compare_chain(rules, scope_stack) { |r| r == -1 }
|
|
28
13
|
end
|
|
29
14
|
end
|
|
30
15
|
end
|
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "shiny_json_logic/operations/base"
|
|
4
|
-
require "shiny_json_logic/numericals/with_error_handling"
|
|
5
4
|
require "shiny_json_logic/comparisons/comparable"
|
|
6
5
|
|
|
7
6
|
module ShinyJsonLogic
|
|
8
7
|
module Operations
|
|
9
8
|
class SmallerEqual < Base
|
|
10
|
-
include Numericals::WithErrorHandling
|
|
11
|
-
include Comparisons::Comparable
|
|
12
9
|
raise_on_dynamic_args!
|
|
13
10
|
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
operands = wrap_nil(rules)
|
|
17
|
-
return handle_invalid_args if operands.length < 2
|
|
18
|
-
|
|
19
|
-
prev = evaluate(operands[0])
|
|
20
|
-
operands[1..].each do |rule|
|
|
21
|
-
curr = evaluate(rule)
|
|
22
|
-
result = compare(prev, curr)
|
|
23
|
-
return handle_nan if result == :nan
|
|
24
|
-
return false unless result <= 0
|
|
25
|
-
prev = curr
|
|
26
|
-
end
|
|
27
|
-
true
|
|
11
|
+
def self.execute(rules, scope_stack)
|
|
12
|
+
Comparisons::Comparable.compare_chain(rules, scope_stack) { |r| r <= 0 }
|
|
28
13
|
end
|
|
29
14
|
end
|
|
30
15
|
end
|
|
@@ -1,33 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "shiny_json_logic/operations/base"
|
|
4
|
+
require "shiny_json_logic/comparisons/comparable"
|
|
4
5
|
require "shiny_json_logic/numericals/with_error_handling"
|
|
5
6
|
|
|
6
7
|
module ShinyJsonLogic
|
|
7
8
|
module Operations
|
|
8
9
|
class StrictDifferent < Base
|
|
9
|
-
|
|
10
|
+
extend Numericals::WithErrorHandling
|
|
10
11
|
raise_on_dynamic_args!
|
|
11
12
|
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
operands = wrap_nil(rules)
|
|
13
|
+
def self.execute(rules, scope_stack)
|
|
14
|
+
operands = Utils::Array.wrap_nil(rules)
|
|
15
15
|
return handle_invalid_args if operands.length < 2
|
|
16
16
|
|
|
17
|
-
prev = cast(evaluate(operands[0]))
|
|
17
|
+
prev = Comparisons::Comparable.cast(evaluate(operands[0], scope_stack))
|
|
18
18
|
operands[1..].each do |rule|
|
|
19
|
-
curr = cast(evaluate(rule))
|
|
19
|
+
curr = Comparisons::Comparable.cast(evaluate(rule, scope_stack))
|
|
20
20
|
return false if curr == prev
|
|
21
21
|
prev = curr
|
|
22
22
|
end
|
|
23
23
|
true
|
|
24
24
|
end
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
def cast(value)
|
|
29
|
-
value.is_a?(Numeric) ? value.to_f : value
|
|
30
|
-
end
|
|
31
25
|
end
|
|
32
26
|
end
|
|
33
27
|
end
|
|
@@ -1,31 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "shiny_json_logic/operations/base"
|
|
4
|
+
require "shiny_json_logic/comparisons/comparable"
|
|
4
5
|
require "shiny_json_logic/numericals/with_error_handling"
|
|
5
6
|
|
|
6
7
|
module ShinyJsonLogic
|
|
7
8
|
module Operations
|
|
8
9
|
class StrictEqual < Base
|
|
9
|
-
|
|
10
|
+
extend Numericals::WithErrorHandling
|
|
10
11
|
raise_on_dynamic_args!
|
|
11
12
|
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
operands = wrap_nil(rules)
|
|
13
|
+
def self.execute(rules, scope_stack)
|
|
14
|
+
operands = Utils::Array.wrap_nil(rules)
|
|
15
15
|
return handle_invalid_args if operands.length < 2
|
|
16
16
|
|
|
17
|
-
first = cast(evaluate(operands[0]))
|
|
17
|
+
first = Comparisons::Comparable.cast(evaluate(operands[0], scope_stack))
|
|
18
18
|
operands[1..].each do |rule|
|
|
19
|
-
return false unless cast(evaluate(rule)) == first
|
|
19
|
+
return false unless Comparisons::Comparable.cast(evaluate(rule, scope_stack)) == first
|
|
20
20
|
end
|
|
21
21
|
true
|
|
22
22
|
end
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
def cast(value)
|
|
27
|
-
value.is_a?(Numeric) ? value.to_f : value
|
|
28
|
-
end
|
|
29
23
|
end
|
|
30
24
|
end
|
|
31
25
|
end
|
|
@@ -5,10 +5,10 @@ require "shiny_json_logic/operations/base"
|
|
|
5
5
|
module ShinyJsonLogic
|
|
6
6
|
module Operations
|
|
7
7
|
class Substring < Base
|
|
8
|
-
def
|
|
9
|
-
str = evaluate(rules[0]).to_s
|
|
10
|
-
start = evaluate(rules[1]).to_i
|
|
11
|
-
length = rules[2] ? evaluate(rules[2]).to_i : str.length
|
|
8
|
+
def self.execute(rules, scope_stack)
|
|
9
|
+
str = evaluate(rules[0], scope_stack).to_s
|
|
10
|
+
start = evaluate(rules[1], scope_stack).to_i
|
|
11
|
+
length = rules[2] ? evaluate(rules[2], scope_stack).to_i : str.length
|
|
12
12
|
start += str.length if start < 0
|
|
13
13
|
start = 0 if start < 0 # clamp negative start to 0
|
|
14
14
|
return "" if start >= str.length
|