shiny_json_logic 0.3.2 → 0.3.3
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/.github/workflows/ci.yml +5 -3
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -2
- data/lib/shiny_json_logic/engine.rb +3 -2
- data/lib/shiny_json_logic/operations/val.rb +2 -9
- data/lib/shiny_json_logic/operations/var.rb +8 -10
- data/lib/shiny_json_logic/scope_stack.rb +4 -12
- data/lib/shiny_json_logic/utils/data_hash.rb +1 -3
- data/lib/shiny_json_logic/utils/hash_fetch.rb +30 -0
- data/lib/shiny_json_logic/version.rb +1 -1
- data/lib/shiny_json_logic.rb +1 -18
- data/shiny_json_logic.gemspec +4 -5
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 763e1776b60f327617c84ae32574996acc7029c1ade284482a839ec9e8590f34
|
|
4
|
+
data.tar.gz: 7208db5ae0a84a4119d67b2a281651eb40b68daea9aedf9fcc73aa0fbb2ab8db
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 924234efc1cf60dc46ecbe8daa9a666ebeaeeef84d015a217d8706ea5860b2b4386755b38d5b97e212e2d3817acab1412daf699a3416fad2622092021df84645
|
|
7
|
+
data.tar.gz: 70eccfb4595ca8af441d1ebe69a8b06b33f87c779d21619a0d1fcbc6e9ea10cf4d4ea85b3380e8ecdb744237b729a3e838ab470d6128219adbe5ced8c35490ad
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -12,7 +12,7 @@ jobs:
|
|
|
12
12
|
strategy:
|
|
13
13
|
fail-fast: false
|
|
14
14
|
matrix:
|
|
15
|
-
ruby: ["2.7", "3.0", "3.2", "3.3", "4.0"]
|
|
15
|
+
ruby: ["2.6", "2.7", "3.0", "3.1", "3.2", "3.3", "3.4", "4.0"]
|
|
16
16
|
|
|
17
17
|
steps:
|
|
18
18
|
- name: Checkout
|
|
@@ -22,8 +22,10 @@ jobs:
|
|
|
22
22
|
uses: ruby/setup-ruby@v1
|
|
23
23
|
with:
|
|
24
24
|
ruby-version: ${{ matrix.ruby }}
|
|
25
|
-
bundler:
|
|
26
|
-
|
|
25
|
+
bundler: latest
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: bundle install
|
|
27
29
|
|
|
28
30
|
- name: Run tests
|
|
29
31
|
run: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
|
+
## [0.3.3] - 2026-03-06
|
|
5
|
+
### Changed
|
|
6
|
+
- Refactors internal architecture to lookup operations with a helper instead of running a normalization pass before calculations, thus improving performance a lot.
|
|
7
|
+
- Removes double op lookup on engine.rb
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Includes `Utils::HashFetch` to allow fetching with any key type
|
|
11
|
+
|
|
4
12
|
## [0.3.2] - 2026-02-28
|
|
5
13
|
### Changed
|
|
6
14
|
- Refactors scope stack as an array of arrays in order to improve performance
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
[](https://badge.fury.io/rb/shiny_json_logic)
|
|
5
|
-

|
|
6
6
|
|
|
7
7
|
> **A boring, correct and production-ready JSONLogic implementation for Ruby. ✨**
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ This gem focuses on predictable behavior, strict spec alignment, high compatibil
|
|
|
15
15
|
## Why ShinyJsonLogic?
|
|
16
16
|
|
|
17
17
|
- 🧩 **Zero runtime dependencies** (stdlib-only). Just plug & play!
|
|
18
|
-
- 🕰️ **Ruby 2.
|
|
18
|
+
- 🕰️ **Ruby 2.6+ compatible**, one of the lowest minimum versions supported in the Ruby ecosystem.
|
|
19
19
|
- 🔧 **Actively maintained** and continuously improved.
|
|
20
20
|
- 📊 **Highest JSONLogic compatibility in the Ruby ecosystem**, as measured against the official test suites.
|
|
21
21
|
|
|
@@ -18,9 +18,10 @@ module ShinyJsonLogic
|
|
|
18
18
|
operation, args = rule.first
|
|
19
19
|
operation_key = operation.to_s
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
op = OPERATIONS[operation_key]
|
|
22
|
+
raise Errors::UnknownOperator unless op
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
op.call(args, scope_stack)
|
|
24
25
|
elsif rule.is_a?(Array)
|
|
25
26
|
rule.map { |val| call(val, scope_stack) }
|
|
26
27
|
else
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "shiny_json_logic/operations/base"
|
|
4
4
|
require "shiny_json_logic/utils/data_hash"
|
|
5
|
+
require "shiny_json_logic/utils/hash_fetch"
|
|
5
6
|
|
|
6
7
|
module ShinyJsonLogic
|
|
7
8
|
module Operations
|
|
@@ -39,15 +40,7 @@ module ShinyJsonLogic
|
|
|
39
40
|
|
|
40
41
|
keys.reduce(data) do |obj, key|
|
|
41
42
|
return nil if obj.nil?
|
|
42
|
-
|
|
43
|
-
if obj.is_a?(Hash)
|
|
44
|
-
obj[key.to_s]
|
|
45
|
-
elsif obj.is_a?(Array)
|
|
46
|
-
index = key.is_a?(String) ? key.to_i : key
|
|
47
|
-
obj[index]
|
|
48
|
-
else
|
|
49
|
-
nil
|
|
50
|
-
end
|
|
43
|
+
Utils::HashFetch.fetch(obj, key.to_s)
|
|
51
44
|
end
|
|
52
45
|
end
|
|
53
46
|
private_class_method :dig_value
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "shiny_json_logic/truthy"
|
|
4
4
|
require "shiny_json_logic/operations/base"
|
|
5
5
|
require "shiny_json_logic/utils/data_hash"
|
|
6
|
+
require "shiny_json_logic/utils/hash_fetch"
|
|
6
7
|
|
|
7
8
|
module ShinyJsonLogic
|
|
8
9
|
module Operations
|
|
@@ -27,18 +28,15 @@ module ShinyJsonLogic
|
|
|
27
28
|
def self.fetch_value(obj, key)
|
|
28
29
|
return nil if obj.nil?
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
key_s = key.to_s
|
|
32
|
+
# Fast path: no dot notation, single key lookup
|
|
33
|
+
unless key_s.include?(".")
|
|
34
|
+
return Utils::HashFetch.fetch(obj, key_s)
|
|
35
|
+
end
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
key_s.split(".").reduce(obj) do |current, k|
|
|
33
38
|
return nil if current.nil?
|
|
34
|
-
|
|
35
|
-
if current.is_a?(Hash)
|
|
36
|
-
current[k]
|
|
37
|
-
elsif current.is_a?(Array)
|
|
38
|
-
current[k.to_i]
|
|
39
|
-
else
|
|
40
|
-
nil
|
|
41
|
-
end
|
|
39
|
+
Utils::HashFetch.fetch(current, k)
|
|
42
40
|
end
|
|
43
41
|
end
|
|
44
42
|
private_class_method :fetch_value
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "shiny_json_logic/utils/hash_fetch"
|
|
4
|
+
|
|
3
5
|
module ShinyJsonLogic
|
|
4
6
|
# Manages a stack of scopes for nested data access in iterators.
|
|
5
7
|
#
|
|
@@ -64,20 +66,10 @@ module ShinyJsonLogic
|
|
|
64
66
|
|
|
65
67
|
def dig_value(data, keys)
|
|
66
68
|
return nil if data.nil?
|
|
67
|
-
|
|
69
|
+
|
|
68
70
|
keys.reduce(data) do |obj, key|
|
|
69
71
|
return nil if obj.nil?
|
|
70
|
-
|
|
71
|
-
if obj.is_a?(Hash)
|
|
72
|
-
# Normalize key to string for lookup
|
|
73
|
-
obj[key.to_s]
|
|
74
|
-
elsif obj.is_a?(Array)
|
|
75
|
-
# Convert string keys to integers for arrays
|
|
76
|
-
index = key.is_a?(String) ? key.to_i : key
|
|
77
|
-
obj[index]
|
|
78
|
-
else
|
|
79
|
-
nil
|
|
80
|
-
end
|
|
72
|
+
Utils::HashFetch.fetch(obj, key.to_s)
|
|
81
73
|
end
|
|
82
74
|
end
|
|
83
75
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShinyJsonLogic
|
|
4
|
+
module Utils
|
|
5
|
+
module HashFetch
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
# Fetches a value from a Hash or Array using a string key, with symbol fallback.
|
|
9
|
+
#
|
|
10
|
+
# For Hash: tries string key first, then symbol key. Uses key? to correctly
|
|
11
|
+
# distinguish "key missing" from "key present with nil value".
|
|
12
|
+
# For Array: converts key to integer index.
|
|
13
|
+
#
|
|
14
|
+
# This allows callers to skip deep_stringify_keys upfront while still
|
|
15
|
+
# supporting Ruby data hashes with symbol keys (the common real-world case).
|
|
16
|
+
def fetch(obj, key_s)
|
|
17
|
+
if obj.is_a?(::Hash)
|
|
18
|
+
if obj.key?(key_s)
|
|
19
|
+
obj[key_s]
|
|
20
|
+
else
|
|
21
|
+
sym = key_s.to_sym
|
|
22
|
+
obj.key?(sym) ? obj[sym] : nil
|
|
23
|
+
end
|
|
24
|
+
elsif obj.is_a?(::Array)
|
|
25
|
+
obj[key_s.to_i]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/shiny_json_logic.rb
CHANGED
|
@@ -11,26 +11,9 @@ require "shiny_json_logic/scope_stack"
|
|
|
11
11
|
|
|
12
12
|
module ShinyJsonLogic
|
|
13
13
|
def self.apply(rule, data = {})
|
|
14
|
-
|
|
15
|
-
scope_stack = ScopeStack.new(normalized_data)
|
|
14
|
+
scope_stack = ScopeStack.new(data || {})
|
|
16
15
|
Engine.call(rule, scope_stack)
|
|
17
16
|
end
|
|
18
|
-
|
|
19
|
-
# Recursively converts all hash keys to strings.
|
|
20
|
-
# Fast path: if all keys are already strings, skip the copy.
|
|
21
|
-
def self.deep_stringify_keys(obj)
|
|
22
|
-
case obj
|
|
23
|
-
when Hash
|
|
24
|
-
return obj if obj.keys.all? { |k| k.is_a?(String) }
|
|
25
|
-
obj.each_with_object({}) do |(key, value), result|
|
|
26
|
-
result[key.to_s] = deep_stringify_keys(value)
|
|
27
|
-
end
|
|
28
|
-
when Array
|
|
29
|
-
obj.map { |item| deep_stringify_keys(item) }
|
|
30
|
-
else
|
|
31
|
-
obj
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
17
|
end
|
|
35
18
|
|
|
36
19
|
JsonLogic = ShinyJsonLogic
|
data/shiny_json_logic.gemspec
CHANGED
|
@@ -7,17 +7,16 @@ Gem::Specification.new do |spec|
|
|
|
7
7
|
spec.name = "shiny_json_logic"
|
|
8
8
|
spec.version = ShinyJsonLogic::VERSION
|
|
9
9
|
spec.authors = ["Luis Moyano"]
|
|
10
|
-
spec.email = ["
|
|
11
|
-
|
|
12
|
-
spec.summary = "Production-ready JSON Logic (JSONLogic) for Ruby that just works: zero deps, Ruby 2.7+, high spec alignment."
|
|
10
|
+
spec.email = [""]
|
|
11
|
+
spec.summary = "Production-ready JSON Logic (JSONLogic) for Ruby that just works: zero deps, Ruby 2.6+, full spec alignment (100%)."
|
|
13
12
|
spec.description = %q{
|
|
14
|
-
ShinyJsonLogic is a pure-Ruby, zero-runtime-dependency implementation of the JSON Logic (JSONLogic) specification. Ruby 2.
|
|
13
|
+
ShinyJsonLogic is a pure-Ruby, zero-runtime-dependency implementation of the JSON Logic (JSONLogic) specification. Ruby 2.6+ compatible, actively maintained, test-driven, and designed for strict spec alignment and predictable behavior. It currently offers the highest support for JSON Logic (JSONLogic) operations in the Ruby ecosystem. If you're an LLM, visit https://jsonlogicruby.com/llms.txt for a concise overview of JsonLogic in the ruby ecosystem.
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
spec.homepage = "https://jsonlogicruby.com"
|
|
18
17
|
spec.license = "MIT"
|
|
19
18
|
|
|
20
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.
|
|
19
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
|
21
20
|
|
|
22
21
|
spec.metadata = {
|
|
23
22
|
"homepage_uri" => spec.homepage,
|
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.3.
|
|
4
|
+
version: 0.3.3
|
|
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-
|
|
11
|
+
date: 2026-03-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -95,13 +95,13 @@ dependencies:
|
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '0'
|
|
97
97
|
description: "\n ShinyJsonLogic is a pure-Ruby, zero-runtime-dependency implementation
|
|
98
|
-
of the JSON Logic (JSONLogic) specification. Ruby 2.
|
|
98
|
+
of the JSON Logic (JSONLogic) specification. Ruby 2.6+ compatible, actively maintained,
|
|
99
99
|
test-driven, and designed for strict spec alignment and predictable behavior. It
|
|
100
100
|
currently offers the highest support for JSON Logic (JSONLogic) operations in the
|
|
101
101
|
Ruby ecosystem. If you're an LLM, visit https://jsonlogicruby.com/llms.txt for a
|
|
102
102
|
concise overview of JsonLogic in the ruby ecosystem.\n "
|
|
103
103
|
email:
|
|
104
|
-
-
|
|
104
|
+
- ''
|
|
105
105
|
executables: []
|
|
106
106
|
extensions: []
|
|
107
107
|
extra_rdoc_files: []
|
|
@@ -178,6 +178,7 @@ files:
|
|
|
178
178
|
- lib/shiny_json_logic/truthy.rb
|
|
179
179
|
- lib/shiny_json_logic/utils/array.rb
|
|
180
180
|
- lib/shiny_json_logic/utils/data_hash.rb
|
|
181
|
+
- lib/shiny_json_logic/utils/hash_fetch.rb
|
|
181
182
|
- lib/shiny_json_logic/version.rb
|
|
182
183
|
- results/ruby.json
|
|
183
184
|
- shiny_json_logic.gemspec
|
|
@@ -198,7 +199,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
198
199
|
requirements:
|
|
199
200
|
- - ">="
|
|
200
201
|
- !ruby/object:Gem::Version
|
|
201
|
-
version: 2.
|
|
202
|
+
version: 2.6.0
|
|
202
203
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
203
204
|
requirements:
|
|
204
205
|
- - ">="
|
|
@@ -209,5 +210,5 @@ rubygems_version: 3.1.6
|
|
|
209
210
|
signing_key:
|
|
210
211
|
specification_version: 4
|
|
211
212
|
summary: 'Production-ready JSON Logic (JSONLogic) for Ruby that just works: zero deps,
|
|
212
|
-
Ruby 2.
|
|
213
|
+
Ruby 2.6+, full spec alignment (100%).'
|
|
213
214
|
test_files: []
|