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
|
@@ -7,18 +7,20 @@ require "shiny_json_logic/numericals/numerify"
|
|
|
7
7
|
module ShinyJsonLogic
|
|
8
8
|
module Operations
|
|
9
9
|
class Subtraction < 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)
|
|
23
|
+
num = 0 if num.nil?
|
|
22
24
|
count += 1
|
|
23
25
|
result = result.nil? ? num : result - num
|
|
24
26
|
end
|
|
@@ -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
|
|
@@ -5,22 +5,20 @@ require "shiny_json_logic/operations/base"
|
|
|
5
5
|
module ShinyJsonLogic
|
|
6
6
|
module Operations
|
|
7
7
|
class Throw < Base
|
|
8
|
-
def
|
|
8
|
+
def self.execute(rules, scope_stack)
|
|
9
9
|
raw_value = rules.is_a?(Array) ? rules[0] : rules
|
|
10
10
|
|
|
11
11
|
error_type =
|
|
12
|
-
if
|
|
13
|
-
evaluate(raw_value)
|
|
12
|
+
if op?(raw_value)
|
|
13
|
+
evaluate(raw_value, scope_stack)
|
|
14
14
|
else
|
|
15
15
|
raw_value
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
extracted_type = error_type.is_a?(Hash) && error_type.key?("type") ? error_type["type"] : error_type
|
|
19
|
-
extracted_type =
|
|
19
|
+
extracted_type = scope_stack.current["type"] if extracted_type.nil?
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
raise error
|
|
21
|
+
raise Errors::Base.new(type: extracted_type)
|
|
24
22
|
end
|
|
25
23
|
end
|
|
26
24
|
end
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
module ShinyJsonLogic
|
|
4
4
|
module Operations
|
|
5
5
|
class Try < Base
|
|
6
|
-
def call
|
|
7
|
-
items = wrap_nil(rules)
|
|
6
|
+
def self.call(rules, scope_stack)
|
|
7
|
+
items = Utils::Array.wrap_nil(rules)
|
|
8
8
|
last_error = nil
|
|
9
9
|
|
|
10
10
|
items.each do |item|
|
|
@@ -33,7 +33,6 @@ module ShinyJsonLogic
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
last_error = e
|
|
36
|
-
# Don't add to errors array - we're handling it
|
|
37
36
|
end
|
|
38
37
|
end
|
|
39
38
|
|
|
@@ -1,56 +1,48 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "shiny_json_logic/operations/base"
|
|
4
|
+
require "shiny_json_logic/utils/data_hash"
|
|
4
5
|
|
|
5
6
|
module ShinyJsonLogic
|
|
6
7
|
module Operations
|
|
7
8
|
class Val < Base
|
|
8
|
-
def
|
|
9
|
-
raw_keys = wrap_nil(rules)
|
|
10
|
-
|
|
9
|
+
def self.execute(rules, scope_stack)
|
|
10
|
+
raw_keys = Utils::Array.wrap_nil(rules)
|
|
11
|
+
|
|
11
12
|
# {"val": []} or {"val": null} - return current scope
|
|
12
13
|
if raw_keys.empty? || raw_keys == [nil]
|
|
13
|
-
return scope_stack
|
|
14
|
+
return Utils::DataHash.wrap(scope_stack.current)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
# Check if first element is an array (scope navigation syntax)
|
|
17
|
-
# {"val": [[N], "key"]} - scope navigation
|
|
18
18
|
first_key = raw_keys.first
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
if first_key.is_a?(Array) && scope_stack
|
|
21
21
|
level_indicator = first_key.first.to_i
|
|
22
22
|
remaining_keys = raw_keys[1..]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# Both positive and negative numbers mean "go up N levels"
|
|
28
|
-
# [[2], "key"] = go up 2 levels
|
|
29
|
-
# [[-2], "key"] = go up 2 levels (same as above)
|
|
23
|
+
|
|
24
|
+
evaluated_keys = remaining_keys.map { |rule| evaluate(rule, scope_stack) }
|
|
25
|
+
|
|
30
26
|
levels = level_indicator.abs
|
|
31
|
-
return scope_stack.resolve(levels, *evaluated_keys)
|
|
27
|
+
return Utils::DataHash.wrap(scope_stack.resolve(levels, *evaluated_keys))
|
|
32
28
|
end
|
|
33
29
|
|
|
34
30
|
# Normal case: {"val": "key"} or {"val": ["key1", "key2"]}
|
|
35
|
-
keys = raw_keys.map { |rule| evaluate(rule) }
|
|
36
|
-
current_data = scope_stack
|
|
37
|
-
dig_value(current_data, keys)
|
|
31
|
+
keys = raw_keys.map { |rule| evaluate(rule, scope_stack) }
|
|
32
|
+
current_data = scope_stack.current
|
|
33
|
+
Utils::DataHash.wrap(dig_value(current_data, keys))
|
|
38
34
|
end
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def dig_value(data, keys)
|
|
36
|
+
def self.dig_value(data, keys)
|
|
43
37
|
return nil if data.nil?
|
|
44
38
|
return data if keys.empty?
|
|
45
|
-
|
|
39
|
+
|
|
46
40
|
keys.reduce(data) do |obj, key|
|
|
47
41
|
return nil if obj.nil?
|
|
48
|
-
|
|
42
|
+
|
|
49
43
|
if obj.is_a?(Hash)
|
|
50
|
-
# Normalize key to string for lookup (data is already string-keyed)
|
|
51
44
|
obj[key.to_s]
|
|
52
45
|
elsif obj.is_a?(Array)
|
|
53
|
-
# Convert string keys to integers for arrays
|
|
54
46
|
index = key.is_a?(String) ? key.to_i : key
|
|
55
47
|
obj[index]
|
|
56
48
|
else
|
|
@@ -58,6 +50,7 @@ module ShinyJsonLogic
|
|
|
58
50
|
end
|
|
59
51
|
end
|
|
60
52
|
end
|
|
53
|
+
private_class_method :dig_value
|
|
61
54
|
end
|
|
62
55
|
end
|
|
63
56
|
end
|
|
@@ -2,36 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
require "shiny_json_logic/truthy"
|
|
4
4
|
require "shiny_json_logic/operations/base"
|
|
5
|
+
require "shiny_json_logic/utils/data_hash"
|
|
5
6
|
|
|
6
7
|
module ShinyJsonLogic
|
|
7
8
|
module Operations
|
|
8
9
|
class Var < Base
|
|
9
|
-
def
|
|
10
|
-
items = wrap_nil(rules)
|
|
11
|
-
key = evaluate(items[0])
|
|
12
|
-
default = items[1] ? evaluate(items[1]) : nil
|
|
10
|
+
def self.execute(rules, scope_stack)
|
|
11
|
+
items = Utils::Array.wrap_nil(rules)
|
|
12
|
+
key = evaluate(items[0], scope_stack)
|
|
13
|
+
default = items[1] ? evaluate(items[1], scope_stack) : nil
|
|
14
|
+
current_data = scope_stack.current
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
if key.nil? || key == ""
|
|
17
|
+
return Utils::DataHash.wrap(current_data)
|
|
18
|
+
end
|
|
15
19
|
|
|
16
|
-
result = fetch_value(
|
|
17
|
-
result.nil? ? default : result
|
|
20
|
+
result = fetch_value(current_data, key)
|
|
21
|
+
result = result.nil? ? default : result
|
|
22
|
+
Utils::DataHash.wrap(result)
|
|
18
23
|
rescue
|
|
19
|
-
default ||
|
|
24
|
+
default || scope_stack.current
|
|
20
25
|
end
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def fetch_value(obj, key)
|
|
27
|
+
def self.fetch_value(obj, key)
|
|
25
28
|
return nil if obj.nil?
|
|
26
|
-
|
|
27
|
-
# Split dot-separated keys
|
|
29
|
+
|
|
28
30
|
keys = key.to_s.split('.')
|
|
29
|
-
|
|
31
|
+
|
|
30
32
|
keys.reduce(obj) do |current, k|
|
|
31
33
|
return nil if current.nil?
|
|
32
|
-
|
|
34
|
+
|
|
33
35
|
if current.is_a?(Hash)
|
|
34
|
-
# Data is already normalized to string keys
|
|
35
36
|
current[k]
|
|
36
37
|
elsif current.is_a?(Array)
|
|
37
38
|
current[k.to_i]
|
|
@@ -40,6 +41,7 @@ module ShinyJsonLogic
|
|
|
40
41
|
end
|
|
41
42
|
end
|
|
42
43
|
end
|
|
44
|
+
private_class_method :fetch_value
|
|
43
45
|
end
|
|
44
46
|
end
|
|
45
47
|
end
|
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
module ShinyJsonLogic
|
|
6
6
|
module Truthy
|
|
7
7
|
def self.call(subject)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
case subject
|
|
9
|
+
when true, false then subject
|
|
10
|
+
when Numeric then !subject.zero?
|
|
11
|
+
when String then !subject.empty?
|
|
12
|
+
when Array then subject.any?
|
|
13
|
+
when Hash then !subject.empty?
|
|
14
|
+
when NilClass then false
|
|
15
|
+
else true
|
|
16
|
+
end
|
|
15
17
|
end
|
|
16
18
|
end
|
|
17
19
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShinyJsonLogic
|
|
4
|
+
module Utils
|
|
5
|
+
# A Hash subclass that marks its contents as user data (result of var/val).
|
|
6
|
+
# The Engine uses this to skip operator validation for these values.
|
|
7
|
+
class DataHash < Hash
|
|
8
|
+
def self.wrap(obj)
|
|
9
|
+
return obj unless obj.is_a?(Hash)
|
|
10
|
+
return obj if obj.is_a?(DataHash)
|
|
11
|
+
|
|
12
|
+
result = new
|
|
13
|
+
obj.each { |k, v| result[k] = v }
|
|
14
|
+
result
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/shiny_json_logic.rb
CHANGED
|
@@ -11,8 +11,6 @@ require "shiny_json_logic/scope_stack"
|
|
|
11
11
|
|
|
12
12
|
module ShinyJsonLogic
|
|
13
13
|
def self.apply(rule, data = {})
|
|
14
|
-
validate_operators!(rule)
|
|
15
|
-
|
|
16
14
|
normalized_data = deep_stringify_keys(data || {})
|
|
17
15
|
scope_stack = ScopeStack.new(normalized_data)
|
|
18
16
|
Engine.call(rule, scope_stack)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shiny_json_logic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Luis Moyano
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -177,6 +177,7 @@ files:
|
|
|
177
177
|
- lib/shiny_json_logic/scope_stack.rb
|
|
178
178
|
- lib/shiny_json_logic/truthy.rb
|
|
179
179
|
- lib/shiny_json_logic/utils/array.rb
|
|
180
|
+
- lib/shiny_json_logic/utils/data_hash.rb
|
|
180
181
|
- lib/shiny_json_logic/version.rb
|
|
181
182
|
- results/ruby.json
|
|
182
183
|
- shiny_json_logic.gemspec
|