json-logic-rb 0.1.5 → 0.2.0
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/README.md +197 -197
- data/lib/json_logic/engine.rb +22 -21
- data/lib/json_logic/enumerable_operation.rb +27 -5
- data/lib/json_logic/errors/error.rb +29 -0
- data/lib/json_logic/errors/invalid_arguments_error.rb +7 -0
- data/lib/json_logic/errors/logic_error.rb +7 -0
- data/lib/json_logic/errors/nan_error.rb +7 -0
- data/lib/json_logic/ext/array.rb +5 -0
- data/lib/json_logic/operations/add.rb +3 -3
- data/lib/json_logic/operations/all.rb +3 -6
- data/lib/json_logic/operations/and.rb +6 -5
- data/lib/json_logic/operations/bool_cast.rb +2 -3
- data/lib/json_logic/operations/cat.rb +3 -1
- data/lib/json_logic/operations/coalesce.rb +9 -0
- data/lib/json_logic/operations/div.rb +7 -1
- data/lib/json_logic/operations/equal.rb +12 -3
- data/lib/json_logic/operations/exists.rb +14 -0
- data/lib/json_logic/operations/filter.rb +11 -3
- data/lib/json_logic/operations/gt.rb +12 -4
- data/lib/json_logic/operations/gte.rb +12 -4
- data/lib/json_logic/operations/if.rb +2 -0
- data/lib/json_logic/operations/in.rb +2 -0
- data/lib/json_logic/operations/lt.rb +10 -4
- data/lib/json_logic/operations/lte.rb +12 -4
- data/lib/json_logic/operations/map.rb +14 -2
- data/lib/json_logic/operations/max.rb +3 -1
- data/lib/json_logic/operations/merge.rb +4 -3
- data/lib/json_logic/operations/min.rb +3 -1
- data/lib/json_logic/operations/missing.rb +4 -26
- data/lib/json_logic/operations/missing_some.rb +6 -20
- data/lib/json_logic/operations/mod.rb +9 -1
- data/lib/json_logic/operations/mul.rb +4 -1
- data/lib/json_logic/operations/none.rb +4 -5
- data/lib/json_logic/operations/not_equal.rb +12 -3
- data/lib/json_logic/operations/or.rb +5 -1
- data/lib/json_logic/operations/preserve.rb +9 -0
- data/lib/json_logic/operations/reduce.rb +21 -5
- data/lib/json_logic/operations/some.rb +4 -7
- data/lib/json_logic/operations/strict_equal.rb +26 -3
- data/lib/json_logic/operations/strict_not_equal.rb +24 -3
- data/lib/json_logic/operations/sub.rb +8 -1
- data/lib/json_logic/operations/substr.rb +12 -20
- data/lib/json_logic/operations/ternary.rb +1 -7
- data/lib/json_logic/operations/throw.rb +12 -0
- data/lib/json_logic/operations/try.rb +35 -0
- data/lib/json_logic/operations/val.rb +79 -0
- data/lib/json_logic/operations/var.rb +22 -20
- data/lib/json_logic/scope.rb +67 -0
- data/lib/json_logic/semantics.rb +107 -38
- data/lib/json_logic/tree.rb +97 -0
- data/lib/json_logic/version.rb +1 -1
- data/lib/json_logic.rb +12 -0
- data/script/build_tests_json.rb +26 -0
- data/script/compliance.rb +160 -37
- data/spec/tmp/v2/tests.json +16981 -0
- metadata +24 -13
- /data/spec/tmp/{tests.json → v1/tests.json} +0 -0
|
@@ -5,12 +5,9 @@ using JsonLogic::Semantics
|
|
|
5
5
|
class JsonLogic::Operations::All < JsonLogic::EnumerableOperation
|
|
6
6
|
def self.name = "all"
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
items, rule_applied_to_each_item = resolve_items_and_per_item_rule(args, data)
|
|
10
|
-
return false if items.empty?
|
|
8
|
+
protected
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
10
|
+
def call_with_values(values)
|
|
11
|
+
!values.empty? && values.all? { |value| !!value }
|
|
15
12
|
end
|
|
16
13
|
end
|
|
@@ -6,11 +6,12 @@ class JsonLogic::Operations::And < JsonLogic::LazyOperation
|
|
|
6
6
|
def self.name = "and"
|
|
7
7
|
|
|
8
8
|
def call(args, data)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array)
|
|
10
|
+
|
|
11
|
+
args.reduce(false) do |_memo, rule|
|
|
12
|
+
value = JsonLogic.apply(rule, data)
|
|
13
|
+
break value unless value.to_bool
|
|
14
|
+
value
|
|
13
15
|
end
|
|
14
|
-
last
|
|
15
16
|
end
|
|
16
17
|
end
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
3
5
|
class JsonLogic::Operations::Div < JsonLogic::Operation
|
|
4
6
|
def self.name = "/"
|
|
5
7
|
|
|
6
|
-
def call(
|
|
8
|
+
def call(args, _data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new if args.empty?
|
|
10
|
+
numbers = args.map(&:to_f)
|
|
11
|
+
numbers.one? ? (1.0 / numbers.first) : numbers.drop(1).reduce(numbers.first, :/)
|
|
12
|
+
end
|
|
7
13
|
end
|
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
using JsonLogic::Semantics
|
|
4
4
|
|
|
5
|
-
class JsonLogic::Operations::Equal < JsonLogic::
|
|
5
|
+
class JsonLogic::Operations::Equal < JsonLogic::LazyOperation
|
|
6
6
|
def self.name = "=="
|
|
7
7
|
|
|
8
|
-
def call(
|
|
9
|
-
|
|
8
|
+
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
10
|
+
|
|
11
|
+
prev = JsonLogic.apply(args.first, data)
|
|
12
|
+
args[1..].each do |arg|
|
|
13
|
+
current = JsonLogic.apply(arg, data)
|
|
14
|
+
return false unless prev == current
|
|
15
|
+
|
|
16
|
+
prev = current
|
|
17
|
+
end
|
|
18
|
+
true
|
|
10
19
|
end
|
|
11
20
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
5
|
+
class JsonLogic::Operations::Exists < JsonLogic::Operation
|
|
6
|
+
def self.name = "exists"
|
|
7
|
+
def self.values_only? = false
|
|
8
|
+
|
|
9
|
+
def call(args, data) = JsonLogic::Tree.new(data).exists?(normalize_path(args, data), split_dots: false)
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def normalize_path(args, data) = args.is_a?(Array) ? Array.wrap(args).map { |part| JsonLogic.apply(part, data) } : JsonLogic.apply(args, data)
|
|
14
|
+
end
|
|
@@ -6,10 +6,18 @@ class JsonLogic::Operations::Filter < JsonLogic::EnumerableOperation
|
|
|
6
6
|
def self.name = "filter"
|
|
7
7
|
|
|
8
8
|
def call(args, data)
|
|
9
|
-
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new if args.is_a?(Array) && args.size >= 2 && args[1].nil?
|
|
10
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
11
|
+
raise JsonLogic::InvalidArgumentsError.new if args[0].nil?
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
items_rule, rule = args
|
|
14
|
+
items = Array(JsonLogic.apply(items_rule, data))
|
|
15
|
+
|
|
16
|
+
return [] if rule.nil?
|
|
17
|
+
|
|
18
|
+
items.each_with_index.each_with_object([]) do |(item, index), filtered|
|
|
19
|
+
value = JsonLogic.apply(rule, JsonLogic::Scope.new(item, data, index))
|
|
20
|
+
filtered << item if value.to_bool
|
|
13
21
|
end
|
|
14
22
|
end
|
|
15
23
|
end
|
|
@@ -2,11 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
using JsonLogic::Semantics
|
|
4
4
|
|
|
5
|
-
class JsonLogic::Operations::GT < JsonLogic::
|
|
5
|
+
class JsonLogic::Operations::GT < JsonLogic::LazyOperation
|
|
6
6
|
def self.name = ">"
|
|
7
7
|
|
|
8
|
-
def call(
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
10
|
+
|
|
11
|
+
previous = JsonLogic.apply(args.first, data)
|
|
12
|
+
args.drop(1).all? do |rule|
|
|
13
|
+
current = JsonLogic.apply(rule, data)
|
|
14
|
+
next false unless previous > current
|
|
15
|
+
|
|
16
|
+
previous = current
|
|
17
|
+
true
|
|
18
|
+
end
|
|
11
19
|
end
|
|
12
20
|
end
|
|
@@ -2,11 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
using JsonLogic::Semantics
|
|
4
4
|
|
|
5
|
-
class JsonLogic::Operations::GTE < JsonLogic::
|
|
5
|
+
class JsonLogic::Operations::GTE < JsonLogic::LazyOperation
|
|
6
6
|
def self.name = ">="
|
|
7
7
|
|
|
8
|
-
def call(
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
10
|
+
|
|
11
|
+
previous = JsonLogic.apply(args.first, data)
|
|
12
|
+
args.drop(1).all? do |rule|
|
|
13
|
+
current = JsonLogic.apply(rule, data)
|
|
14
|
+
next false unless previous >= current
|
|
15
|
+
|
|
16
|
+
previous = current
|
|
17
|
+
true
|
|
18
|
+
end
|
|
11
19
|
end
|
|
12
20
|
end
|
|
@@ -6,6 +6,8 @@ class JsonLogic::Operations::If < JsonLogic::LazyOperation
|
|
|
6
6
|
def self.name = "if"
|
|
7
7
|
|
|
8
8
|
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array)
|
|
10
|
+
|
|
9
11
|
i = 0
|
|
10
12
|
while i < args.size - 1
|
|
11
13
|
return JsonLogic.apply(args[i + 1], data) if !!(JsonLogic.apply(args[i], data))
|
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
using JsonLogic::Semantics
|
|
4
4
|
|
|
5
|
-
class JsonLogic::Operations::LT < JsonLogic::
|
|
5
|
+
class JsonLogic::Operations::LT < JsonLogic::LazyOperation
|
|
6
6
|
def self.name = "<"
|
|
7
7
|
|
|
8
|
-
def call(
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
10
|
+
|
|
11
|
+
args.drop(1).reduce(JsonLogic.apply(args.first, data)) do |previous, rule|
|
|
12
|
+
current = JsonLogic.apply(rule, data)
|
|
13
|
+
return false unless previous < current
|
|
14
|
+
current
|
|
15
|
+
end
|
|
16
|
+
true
|
|
11
17
|
end
|
|
12
18
|
end
|
|
@@ -2,11 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
using JsonLogic::Semantics
|
|
4
4
|
|
|
5
|
-
class JsonLogic::Operations::LTE < JsonLogic::
|
|
5
|
+
class JsonLogic::Operations::LTE < JsonLogic::LazyOperation
|
|
6
6
|
def self.name = "<="
|
|
7
7
|
|
|
8
|
-
def call(
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
10
|
+
|
|
11
|
+
previous = JsonLogic.apply(args.first, data)
|
|
12
|
+
args.drop(1).all? do |rule|
|
|
13
|
+
current = JsonLogic.apply(rule, data)
|
|
14
|
+
next false unless previous <= current
|
|
15
|
+
|
|
16
|
+
previous = current
|
|
17
|
+
true
|
|
18
|
+
end
|
|
11
19
|
end
|
|
12
20
|
end
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
3
5
|
class JsonLogic::Operations::Map < JsonLogic::EnumerableOperation
|
|
4
6
|
def self.name = "map"
|
|
5
7
|
|
|
6
8
|
def call(args, data)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new if args.is_a?(Array) && args.size >= 2 && args[1].nil?
|
|
10
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
11
|
+
raise JsonLogic::InvalidArgumentsError.new if args[0].nil?
|
|
12
|
+
|
|
13
|
+
items_rule, rule = args
|
|
14
|
+
items = Array(JsonLogic.apply(items_rule, data))
|
|
15
|
+
|
|
16
|
+
return [] if rule.nil?
|
|
17
|
+
|
|
18
|
+
items.each_with_index.map do |item, index|
|
|
19
|
+
JsonLogic.apply(rule, JsonLogic::Scope.new(item, data, index))
|
|
20
|
+
end
|
|
9
21
|
end
|
|
10
22
|
end
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
3
5
|
class JsonLogic::Operations::Merge < JsonLogic::Operation
|
|
4
6
|
def self.name = "merge"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
end
|
|
7
|
+
|
|
8
|
+
def call(args, _data) = args.flat_map { |v| v.is_a?(Array) ? v : [v] }
|
|
8
9
|
end
|
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
3
5
|
class JsonLogic::Operations::Missing < JsonLogic::Operation
|
|
4
6
|
def self.name = "missing"
|
|
5
7
|
|
|
6
|
-
def call(
|
|
7
|
-
|
|
8
|
-
if values.size == 1 && values.first.is_a?(Array)
|
|
9
|
-
values.first
|
|
10
|
-
else
|
|
11
|
-
values
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
keys.select { |k| dig(data, k).nil? }
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
|
|
19
|
-
def dig(obj, path)
|
|
20
|
-
return nil if obj.nil?
|
|
21
|
-
cur = obj
|
|
22
|
-
path.to_s.split(".").each do |k|
|
|
23
|
-
if cur.is_a?(Array) && k =~ /\A\d+\z/
|
|
24
|
-
cur = cur[k.to_i]
|
|
25
|
-
elsif cur.is_a?(Hash)
|
|
26
|
-
cur = cur[k] || cur[k.to_s] || cur[k.to_sym]
|
|
27
|
-
else
|
|
28
|
-
return nil
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
cur
|
|
8
|
+
def call(args, data)
|
|
9
|
+
Array.wrap(args).select { |key| JsonLogic::Tree.new(data).dig(key).nil? }
|
|
32
10
|
end
|
|
33
11
|
end
|
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
3
5
|
class JsonLogic::Operations::MissingSome < JsonLogic::Operation
|
|
4
6
|
def self.name = "missing_some"
|
|
5
7
|
|
|
6
8
|
def call((min_ok, list), data)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
|
|
14
|
-
def dig(obj, path)
|
|
15
|
-
return nil if obj.nil?
|
|
16
|
-
cur = obj
|
|
17
|
-
path.to_s.split(".").each do |k|
|
|
18
|
-
if cur.is_a?(Array) && k =~ /\A\d+\z/
|
|
19
|
-
cur = cur[k.to_i]
|
|
20
|
-
elsif cur.is_a?(Hash)
|
|
21
|
-
cur = cur[k] || cur[k.to_s] || cur[k.to_sym]
|
|
22
|
-
else
|
|
23
|
-
return nil
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
cur
|
|
9
|
+
json = JsonLogic::Tree.new(data)
|
|
10
|
+
keys = Array.wrap(list)
|
|
11
|
+
missing = keys.select { |key| json.dig(key).nil? }
|
|
12
|
+
(keys.size - missing.size) >= min_ok ? [] : missing
|
|
27
13
|
end
|
|
28
14
|
end
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
3
5
|
class JsonLogic::Operations::Mod < JsonLogic::Operation
|
|
4
6
|
def self.name = "%"
|
|
5
7
|
|
|
6
|
-
def call(
|
|
8
|
+
def call(args, _data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new if args.size < 2
|
|
10
|
+
numbers = args.map(&:to_f)
|
|
11
|
+
numbers.drop(1).reduce(numbers.first) do |result, divisor|
|
|
12
|
+
result - divisor * (result / divisor).truncate
|
|
13
|
+
end
|
|
14
|
+
end
|
|
7
15
|
end
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
3
5
|
class JsonLogic::Operations::Mul < JsonLogic::Operation
|
|
4
6
|
def self.name = "*"
|
|
5
|
-
|
|
7
|
+
|
|
8
|
+
def call(args, _data) = args.map(&:to_f).reduce(1.0, :*)
|
|
6
9
|
end
|
|
@@ -5,10 +5,9 @@ using JsonLogic::Semantics
|
|
|
5
5
|
class JsonLogic::Operations::None < JsonLogic::EnumerableOperation
|
|
6
6
|
def self.name = "none"
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
end
|
|
8
|
+
protected
|
|
9
|
+
|
|
10
|
+
def call_with_values(values)
|
|
11
|
+
values.none? { |value| !!value }
|
|
13
12
|
end
|
|
14
13
|
end
|
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
using JsonLogic::Semantics
|
|
4
4
|
|
|
5
|
-
class JsonLogic::Operations::NotEqual < JsonLogic::
|
|
5
|
+
class JsonLogic::Operations::NotEqual < JsonLogic::LazyOperation
|
|
6
6
|
def self.name = "!="
|
|
7
7
|
|
|
8
|
-
def call(
|
|
9
|
-
|
|
8
|
+
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
10
|
+
|
|
11
|
+
prev = JsonLogic.apply(args.first, data)
|
|
12
|
+
args[1..].each do |arg|
|
|
13
|
+
current = JsonLogic.apply(arg, data)
|
|
14
|
+
return false if prev == current
|
|
15
|
+
|
|
16
|
+
prev = current
|
|
17
|
+
end
|
|
18
|
+
true
|
|
10
19
|
end
|
|
11
20
|
end
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
using JsonLogic::Semantics
|
|
4
|
+
|
|
4
5
|
class JsonLogic::Operations::Or < JsonLogic::LazyOperation
|
|
5
6
|
def self.name = "or"
|
|
6
7
|
|
|
7
8
|
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array)
|
|
10
|
+
return false if args.empty?
|
|
11
|
+
|
|
8
12
|
args.each do |a|
|
|
9
13
|
v = JsonLogic.apply(a, data)
|
|
10
14
|
return v if !!v
|
|
11
15
|
end
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
JsonLogic.apply(args.last, data)
|
|
14
18
|
end
|
|
15
19
|
end
|
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
3
5
|
class JsonLogic::Operations::Reduce < JsonLogic::EnumerableOperation
|
|
4
6
|
def self.name = "reduce"
|
|
5
7
|
|
|
6
8
|
def call(args, data)
|
|
7
|
-
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
10
|
+
|
|
11
|
+
rule_that_returns_items = args[0]
|
|
12
|
+
step_rule_applied_per_item = args[1]
|
|
13
|
+
rule_that_returns_initial_accumulator = args[2]
|
|
14
|
+
raise JsonLogic::InvalidArgumentsError.new if step_rule_applied_per_item.nil?
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
items_value = JsonLogic.apply(rule_that_returns_items, data)
|
|
17
|
+
items = Array(items_value)
|
|
18
|
+
acc = rule_that_returns_initial_accumulator.nil? ? nil : JsonLogic.apply(rule_that_returns_initial_accumulator, data)
|
|
11
19
|
|
|
12
|
-
items.reduce(acc) do |memo, item|
|
|
20
|
+
items.each_with_index.reduce(acc) do |memo, (item, idx)|
|
|
21
|
+
base_data = data.is_a?(Hash) ? data : {}
|
|
13
22
|
JsonLogic.apply(
|
|
14
23
|
step_rule_applied_per_item,
|
|
15
|
-
|
|
24
|
+
base_data.merge(
|
|
25
|
+
"" => item,
|
|
26
|
+
"current" => item,
|
|
27
|
+
"accumulator" => memo,
|
|
28
|
+
"index" => idx,
|
|
29
|
+
"__parent__" => data,
|
|
30
|
+
"__scope__" => true
|
|
31
|
+
)
|
|
16
32
|
)
|
|
17
33
|
end
|
|
18
34
|
end
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
# frozen_string_literal:
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
using JsonLogic::Semantics
|
|
4
4
|
|
|
5
5
|
class JsonLogic::Operations::Some < JsonLogic::EnumerableOperation
|
|
6
6
|
def self.name = "some"
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
items, rule_applied_to_each_item = resolve_items_and_per_item_rule(args, data)
|
|
10
|
-
return false if items.empty?
|
|
8
|
+
protected
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
10
|
+
def call_with_values(values)
|
|
11
|
+
!values.empty? && values.any? { |value| !!value }
|
|
15
12
|
end
|
|
16
13
|
end
|
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
using JsonLogic::Semantics
|
|
4
|
+
|
|
5
|
+
class JsonLogic::Operations::StrictEqual < JsonLogic::LazyOperation
|
|
4
6
|
def self.name = "==="
|
|
5
7
|
|
|
6
|
-
def call(
|
|
7
|
-
|
|
8
|
+
def call(args, data)
|
|
9
|
+
raise JsonLogic::InvalidArgumentsError.new unless args.is_a?(Array) && args.size >= 2
|
|
10
|
+
|
|
11
|
+
prev = JsonLogic.apply(args.first, data)
|
|
12
|
+
args[1..].each do |arg|
|
|
13
|
+
current = JsonLogic.apply(arg, data)
|
|
14
|
+
return false unless strict_equal_value?(prev, current)
|
|
15
|
+
|
|
16
|
+
prev = current
|
|
17
|
+
end
|
|
18
|
+
true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def strict_equal_value?(left, right)
|
|
24
|
+
if left.is_a?(Numeric) && right.is_a?(Numeric)
|
|
25
|
+
left.to_f == right.to_f
|
|
26
|
+
elsif left.is_a?(Array) || left.is_a?(Hash)
|
|
27
|
+
left.equal?(right)
|
|
28
|
+
else
|
|
29
|
+
left.class == right.class && left.eql?(right)
|
|
30
|
+
end
|
|
8
31
|
end
|
|
9
32
|
end
|