shiny_json_logic 0.2.13 → 0.2.15

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/compat.yml +2 -2
  3. data/CHANGELOG.md +9 -0
  4. data/Gemfile.lock +1 -1
  5. data/README.md +38 -2
  6. data/badges/compat.json +2 -2
  7. data/bin/test.sh +8 -67
  8. data/lib/shiny_json_logic/engine.rb +4 -1
  9. data/lib/shiny_json_logic/errors/base.rb +2 -0
  10. data/lib/shiny_json_logic/errors/invalid_arguments.rb +2 -0
  11. data/lib/shiny_json_logic/errors/not_a_number.rb +2 -0
  12. data/lib/shiny_json_logic/errors/unknown_operator.rb +2 -0
  13. data/lib/shiny_json_logic/numericals/min_max_collection.rb +13 -8
  14. data/lib/shiny_json_logic/numericals/numerify.rb +7 -4
  15. data/lib/shiny_json_logic/numericals/with_error_handling.rb +2 -0
  16. data/lib/shiny_json_logic/operations/addition.rb +2 -0
  17. data/lib/shiny_json_logic/operations/all.rb +2 -0
  18. data/lib/shiny_json_logic/operations/and.rb +2 -0
  19. data/lib/shiny_json_logic/operations/base.rb +3 -1
  20. data/lib/shiny_json_logic/operations/coalesce.rb +2 -0
  21. data/lib/shiny_json_logic/operations/concatenation.rb +2 -0
  22. data/lib/shiny_json_logic/operations/different.rb +2 -0
  23. data/lib/shiny_json_logic/operations/division.rb +2 -0
  24. data/lib/shiny_json_logic/operations/double_not.rb +2 -0
  25. data/lib/shiny_json_logic/operations/equal.rb +2 -0
  26. data/lib/shiny_json_logic/operations/exists.rb +2 -0
  27. data/lib/shiny_json_logic/operations/filter.rb +2 -0
  28. data/lib/shiny_json_logic/operations/greater.rb +2 -0
  29. data/lib/shiny_json_logic/operations/greater_equal.rb +2 -0
  30. data/lib/shiny_json_logic/operations/if.rb +2 -0
  31. data/lib/shiny_json_logic/operations/inclusion.rb +2 -0
  32. data/lib/shiny_json_logic/operations/iterable/base.rb +2 -0
  33. data/lib/shiny_json_logic/operations/map.rb +2 -0
  34. data/lib/shiny_json_logic/operations/max.rb +2 -0
  35. data/lib/shiny_json_logic/operations/merge.rb +2 -0
  36. data/lib/shiny_json_logic/operations/min.rb +2 -0
  37. data/lib/shiny_json_logic/operations/missing.rb +2 -0
  38. data/lib/shiny_json_logic/operations/missing_some.rb +2 -0
  39. data/lib/shiny_json_logic/operations/modulo.rb +2 -0
  40. data/lib/shiny_json_logic/operations/none.rb +2 -0
  41. data/lib/shiny_json_logic/operations/not.rb +2 -0
  42. data/lib/shiny_json_logic/operations/or.rb +2 -0
  43. data/lib/shiny_json_logic/operations/preserve.rb +2 -0
  44. data/lib/shiny_json_logic/operations/product.rb +2 -0
  45. data/lib/shiny_json_logic/operations/reduce.rb +2 -0
  46. data/lib/shiny_json_logic/operations/smaller.rb +2 -0
  47. data/lib/shiny_json_logic/operations/smaller_equal.rb +2 -0
  48. data/lib/shiny_json_logic/operations/some.rb +2 -0
  49. data/lib/shiny_json_logic/operations/strict_different.rb +2 -0
  50. data/lib/shiny_json_logic/operations/strict_equal.rb +2 -0
  51. data/lib/shiny_json_logic/operations/substring.rb +2 -0
  52. data/lib/shiny_json_logic/operations/subtraction.rb +2 -0
  53. data/lib/shiny_json_logic/operations/throw.rb +2 -0
  54. data/lib/shiny_json_logic/operations/try.rb +2 -0
  55. data/lib/shiny_json_logic/operations/val.rb +2 -0
  56. data/lib/shiny_json_logic/operations/var.rb +2 -0
  57. data/lib/shiny_json_logic/operator_solver.rb +51 -47
  58. data/lib/shiny_json_logic/truthy.rb +2 -0
  59. data/lib/shiny_json_logic/version.rb +3 -1
  60. data/lib/shiny_json_logic.rb +3 -1
  61. data/results/ruby.json +2 -2
  62. metadata +2 -7
  63. data/.idea/.gitignore +0 -8
  64. data/.idea/modules.xml +0 -8
  65. data/.idea/shiny_json_logic.iml +0 -55
  66. data/.idea/vcs.xml +0 -6
  67. data/.travis.yml +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f37a7b736cfaaa7084af3c1c09431a5a0f3e4c698b53ea4749aaa866e6c4956f
4
- data.tar.gz: '0386a68e00b8152446ad949a9b848a14a79b18a9b638ed5162bb58d77228d3e5'
3
+ metadata.gz: ff0a154c1e7efab1b183eec02c91b413311ede5763a920563ff1e72eaac3aa2d
4
+ data.tar.gz: 51ec7875a3f873d33463b416d415b94b5cf495715ff451735d68e1f9e50a918d
5
5
  SHA512:
6
- metadata.gz: 3e2b48c589fe1df7f858f21ce6c859c0638fcbad73a1151dd3ba338629f38b8b1f4fe7d1a4c87934d2958b8f270198d36624cea665c01a1f1077133e71c2f5bf
7
- data.tar.gz: 105690bfaa792c6b2f45ab6d36c6ae968fdd1ac1e39c4997d4ed95fdc08d35712cc96d2d1dc2bf1623c288304e437b93b64c4a88f0c0284ba575ca198299643f
6
+ metadata.gz: 835be2a2c516c43edfe0c89736c68ca4792f12912e87d11b1325009e0ac1447ee5d94f4efcbe2adb3d1e53f01f22643b019e01b6874e8d743946faeb0c0911ce
7
+ data.tar.gz: a3e86add800f4dbde67e1c566e094209a3a9c9c32debaa1ed6101e62ce0188d01a356a3108752f708ea00ff6f5c49da911f964fda9b87400e73314e628874300
@@ -45,14 +45,14 @@ jobs:
45
45
  cat > badges/compat.json <<EOF
46
46
  {
47
47
  "schemaVersion": 1,
48
- "label": "compat",
48
+ "label": "official tests",
49
49
  "message": "${PCT}% (${PASSED}/${TOTAL})",
50
50
  "color": "${COLOR}"
51
51
  }
52
52
  EOF
53
53
 
54
54
  {
55
- echo "## JSONLogic compatibility"
55
+ echo "## JSONLogic compatibility (official tests)"
56
56
  echo ""
57
57
  echo "- **${PCT}%** (${PASSED}/${TOTAL})"
58
58
  echo "- exit code (ignored): ${exit_code:-0}"
data/CHANGELOG.md CHANGED
@@ -1,6 +1,15 @@
1
1
  # Changelog
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
+ ## [0.2.15] - 2026-02-15
5
+ ### Changed
6
+ - Refactors operation solvers to improve performance.
7
+ - Includes frozen string literals to optimize string handling.
8
+ - Stops relying in compat tables as a measure of validity.
9
+
10
+ ## [0.2.14] - 2026-02-14
11
+ ### Fixed
12
+ - `max`/`min` operators no longer incorrectly expand arrays from operations inside array wrapper.
4
13
 
5
14
  ## [0.2.13] - 2026-02-09
6
15
  ### Changed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shiny_json_logic (0.2.13)
4
+ shiny_json_logic (0.2.15)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -161,13 +161,49 @@ Currently implemented operators include:
161
161
  📌 **Note:**
162
162
  `val`, `exists`, `??`, `try`, `throw` and `preserve` are **only supported by ShinyJsonLogic** among Ruby implementations.
163
163
 
164
- (See `lib/shiny_json_logic/operations` for the authoritative list.)
164
+ See the [spec](https://jsonlogicruby.com/docs) for the full list of operators and their behavior.
165
+
166
+ ---
167
+
168
+ ## Error Handling
169
+
170
+ ShinyJsonLogic uses native Ruby exceptions for error handling:
171
+
172
+ ```ruby
173
+ # Unknown operators raise an error
174
+ ShinyJsonLogic.apply({ "unknown_op" => [1, 2] }, {})
175
+ # => raises ShinyJsonLogic::Errors::UnknownOperator
176
+
177
+ # Invalid arguments raise an error
178
+ ShinyJsonLogic.apply({ "+" => ["not", "numbers"] }, {})
179
+ # => raises ShinyJsonLogic::Errors::InvalidArguments
180
+
181
+ # You can use try/throw for controlled error handling within rules
182
+ rule = {
183
+ "try" => [
184
+ { "throw" => "Something went wrong" },
185
+ { "cat" => ["Error: ", { "var" => "type" }] }
186
+ ]
187
+ }
188
+ ShinyJsonLogic.apply(rule, {})
189
+ # => "Error: Something went wrong"
190
+ ```
191
+
192
+ Error classes:
193
+ - `ShinyJsonLogic::Errors::UnknownOperator` - Unknown operator in rule
194
+ - `ShinyJsonLogic::Errors::InvalidArguments` - Invalid arguments to operator
195
+ - `ShinyJsonLogic::Errors::NotANumber` - NaN result in numeric operation
165
196
 
166
197
  ---
167
198
 
168
199
  ## Compatibility
169
200
 
170
- Compatibility is measured automatically against the official JSONLogic test suites from `json-logic/compat-tables`.
201
+ Compatibility is measured against the official JSONLogic test suite (`json-logic/.github/tests`):
202
+
203
+ | Test Suite | Status |
204
+ |------------|--------|
205
+ | **Official tests** | 100% (601/601) |
206
+
171
207
  See `badges/compat.json` for the exact numbers behind the badge.
172
208
 
173
209
  ---
data/badges/compat.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "label": "compat",
4
- "message": "99.2% (1117/1126)",
3
+ "label": "official tests",
4
+ "message": "100.0% (601/601)",
5
5
  "color": "green"
6
6
  }
data/bin/test.sh CHANGED
@@ -5,12 +5,9 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
5
  cd "$ROOT_DIR"
6
6
 
7
7
  # Config
8
- COMPAT_REF="${COMPAT_REF:-main}"
9
- COMPAT_REPO="${COMPAT_REPO:-json-logic/compat-tables}"
10
8
  OFFICIAL_REF="${OFFICIAL_REF:-main}"
11
9
  OFFICIAL_REPO="${OFFICIAL_REPO:-json-logic/.github}"
12
10
  TMP_DIR="${TMP_DIR:-$ROOT_DIR/tmp}"
13
- SUITES_DIR="$TMP_DIR/compat-suites"
14
11
  OFFICIAL_DIR="$TMP_DIR/official-tests"
15
12
 
16
13
  # Helpers
@@ -19,27 +16,7 @@ log() { printf "\n\033[1m%s\033[0m\n" "$*"; }
19
16
  log "Installing gems"
20
17
  bundle install
21
18
 
22
- # ---- Compatibility suites (optional but recommended) ----
23
- # Download ONLY the suites folder from the compat-tables repo archive.
24
- # This avoids a full git clone and works everywhere as long as curl+tar exist.
25
-
26
- log "Fetching compat suites from GitHub: $COMPAT_REPO@$COMPAT_REF"
27
-
28
- rm -rf "$SUITES_DIR"
29
- mkdir -p "$SUITES_DIR"
30
-
31
- ARCHIVE_URL="https://codeload.github.com/${COMPAT_REPO}/tar.gz/${COMPAT_REF}"
32
-
33
- # Extract only: compat-tables-<ref>/suites -> tmp/compat-suites
34
- # Different refs create different top-level folder names; we strip the first path component.
35
- curl -fsSL "$ARCHIVE_URL" \
36
- | tar -xz \
37
- --strip-components=2 \
38
- -C "$SUITES_DIR" \
39
- "compat-tables-${COMPAT_REF}/suites" 2>/dev/null \
40
-
41
- log "Compat suites ready at: $SUITES_DIR"
42
-
19
+ # ---- Official tests (json-logic/.github/tests) ----
43
20
  log "Fetching official tests from GitHub: $OFFICIAL_REPO@$OFFICIAL_REF"
44
21
 
45
22
  rm -rf "$OFFICIAL_DIR"
@@ -56,12 +33,12 @@ curl -fsSL "$OFFICIAL_URL" \
56
33
 
57
34
  log "Official tests ready at: $OFFICIAL_DIR"
58
35
 
59
- log "Running compatibility suite"
60
- COMPAT_OUT="$TMP_DIR/compat-rspec.out"
36
+ log "Running official tests"
37
+ OFFICIAL_OUT="$TMP_DIR/official-rspec.out"
61
38
 
62
39
  set +e
63
- COMPAT_SUITES_DIR="$SUITES_DIR" bundle exec rspec spec/compatibility_spec.rb | tee "$COMPAT_OUT"
64
- COMPAT_EXIT=${PIPESTATUS[0]}
40
+ OFFICIAL_TESTS_DIR="$OFFICIAL_DIR" bundle exec rspec spec/official_spec.rb | tee "$OFFICIAL_OUT"
41
+ OFFICIAL_EXIT=${PIPESTATUS[0]}
65
42
  set -e
66
43
 
67
44
  # Parse totals from RSpec summary
@@ -70,14 +47,14 @@ TOTAL=$(ruby -e '
70
47
  m = s.match(/(\d+)\s+examples?,\s+(\d+)\s+failures?/)
71
48
  abort "Could not parse RSpec summary" unless m
72
49
  puts m[1]
73
- ' < "$COMPAT_OUT")
50
+ ' < "$OFFICIAL_OUT")
74
51
 
75
52
  FAILURES=$(ruby -e '
76
53
  s = STDIN.read
77
54
  m = s.match(/(\d+)\s+examples?,\s+(\d+)\s+failures?/)
78
55
  abort "Could not parse RSpec summary" unless m
79
56
  puts m[2]
80
- ' < "$COMPAT_OUT")
57
+ ' < "$OFFICIAL_OUT")
81
58
 
82
59
  PASSED=$((TOTAL - FAILURES))
83
60
 
@@ -93,42 +70,6 @@ cat > results/ruby.json <<EOF
93
70
  }
94
71
  EOF
95
72
 
96
- echo "Compat: ${PASSED}/${TOTAL} (failures: ${FAILURES}, exit: ${COMPAT_EXIT})"
97
-
98
- # ---- Official tests (informational only, does not affect badge) ----
99
- log "Running official tests (informational)"
100
- OFFICIAL_OUT="$TMP_DIR/official-rspec.out"
101
-
102
- set +e
103
- OFFICIAL_TESTS_DIR="$OFFICIAL_DIR" bundle exec rspec spec/official_spec.rb | tee "$OFFICIAL_OUT"
104
- OFFICIAL_EXIT=${PIPESTATUS[0]}
105
- set -e
106
-
107
- # Parse totals from RSpec summary
108
- OFFICIAL_TOTAL=$(ruby -e '
109
- s = STDIN.read
110
- m = s.match(/(\d+)\s+examples?,\s+(\d+)\s+failures?/)
111
- if m
112
- puts m[1]
113
- else
114
- puts "0"
115
- end
116
- ' < "$OFFICIAL_OUT")
117
-
118
- OFFICIAL_FAILURES=$(ruby -e '
119
- s = STDIN.read
120
- m = s.match(/(\d+)\s+examples?,\s+(\d+)\s+failures?/)
121
- if m
122
- puts m[2]
123
- else
124
- puts "0"
125
- end
126
- ' < "$OFFICIAL_OUT")
127
-
128
- OFFICIAL_PASSED=$((OFFICIAL_TOTAL - OFFICIAL_FAILURES))
129
-
130
- echo "Official: ${OFFICIAL_PASSED}/${OFFICIAL_TOTAL} (failures: ${OFFICIAL_FAILURES}, exit: ${OFFICIAL_EXIT})"
131
73
  echo ""
132
74
  echo "=== Summary ==="
133
- echo "Compat (badge): ${PASSED}/${TOTAL}"
134
- echo "Official (info): ${OFFICIAL_PASSED}/${OFFICIAL_TOTAL}"
75
+ echo "Official: ${PASSED}/${TOTAL} (failures: ${FAILURES}, exit: ${OFFICIAL_EXIT})"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operator_solver"
2
4
 
3
5
  module ShinyJsonLogic
@@ -13,6 +15,7 @@ module ShinyJsonLogic
13
15
 
14
16
  operation, args = rule.to_a.first
15
17
  operation_key = operation.to_s
18
+
16
19
  return rule unless operations.key?(operation_key)
17
20
 
18
21
  operations.fetch(operation_key).new(args, scope_stack).call
@@ -28,7 +31,7 @@ module ShinyJsonLogic
28
31
  attr_reader :rule, :scope_stack
29
32
 
30
33
  def operations
31
- @operations ||= OperatorSolver.new.solvers
34
+ OperatorSolver::SOLVERS
32
35
  end
33
36
  end
34
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ShinyJsonLogic
2
4
  module Errors
3
5
  class Base < StandardError
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/errors/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/errors/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/errors/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/errors/invalid_arguments"
2
4
 
3
5
  module ShinyJsonLogic
@@ -13,16 +15,19 @@ module ShinyJsonLogic
13
15
  end
14
16
 
15
17
  def collect_values
18
+ # Logic chaining: if rules is a single operation, expand the result
19
+ # e.g., {"max": {"val": "data"}} where data is [1,2,3] -> max of 1,2,3
20
+ if operation?(rules)
21
+ evaluated = evaluate(rules)
22
+ return wrap_nil(evaluated)
23
+ end
24
+
25
+ # Otherwise, rules is an array of arguments - evaluate each without expanding
26
+ # e.g., {"max": [1, 2, 3]} or {"max": [1, {"val": "x"}]}
27
+ # Note: {"max": [{"val": "data"}]} where data is [1,2,3] -> invalid (array is one element)
16
28
  result = []
17
29
  wrap_nil(rules).each do |rule|
18
- evaluated = evaluate(rule)
19
- # If rule was an operation (Hash), expand the result array
20
- # If rule was a literal array, it's invalid (will fail numeric check)
21
- if operation?(rule)
22
- wrap_nil(evaluated).each { |val| result << val }
23
- else
24
- result << evaluated
25
- end
30
+ result << evaluate(rule)
26
31
  end
27
32
  result
28
33
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ShinyJsonLogic
2
4
  module Numericals
3
5
  module Numerify
@@ -14,11 +16,12 @@ module ShinyJsonLogic
14
16
  raise TypeError, "Cannot convert #{value.inspect} to a number"
15
17
  end
16
18
 
19
+ # Regex to match valid numeric strings (integers, floats, scientific notation)
20
+ # Examples: "123", "-45.67", "+3.14", "1e10", "2.5E-3", ".5", "-.5"
21
+ NUMERIC_REGEX = /\A[+-]?(?:\d+\.?\d*|\d*\.?\d+)(?:[eE][+-]?\d+)?\z/
22
+
17
23
  def numeric_string?(value)
18
- Float(value)
19
- true
20
- rescue ArgumentError
21
- false
24
+ NUMERIC_REGEX.match?(value)
22
25
  end
23
26
  end
24
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/errors/base"
2
4
  require "shiny_json_logic/errors/not_a_number"
3
5
  require "shiny_json_logic/errors/invalid_arguments"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/numericals/numerify"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/iterable/base"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/truthy"
3
5
  require "shiny_json_logic/numericals/with_error_handling"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/utils/array"
3
5
 
@@ -53,7 +55,7 @@ module ShinyJsonLogic
53
55
  def operation?(value)
54
56
  return false unless value.is_a?(Hash) && !value.empty?
55
57
 
56
- OperatorSolver.new.operation?(value)
58
+ OperatorSolver.operation?(value)
57
59
  end
58
60
  end
59
61
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/comparisons/comparable"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/numericals/numerify"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/truthy"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/comparisons/comparable"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/iterable/base"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/comparisons/comparable"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/comparisons/comparable"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/base"
3
5
  require "shiny_json_logic/numericals/with_error_handling"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/iterable/base"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/min_max_collection"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/min_max_collection"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/base"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/missing"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/numericals/numerify"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/iterable/base"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/truthy"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/truthy"
3
5
  require "shiny_json_logic/numericals/with_error_handling"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/numericals/numerify"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/iterable/base"
3
5
  require "shiny_json_logic/numericals/with_error_handling"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/comparisons/comparable"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/comparisons/comparable"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/iterable/base"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
  require "shiny_json_logic/numericals/with_error_handling"
3
5
  require "shiny_json_logic/numericals/numerify"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ShinyJsonLogic
2
4
  module Operations
3
5
  class Try < Base
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/operations/base"
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/truthy"
2
4
  require "shiny_json_logic/operations/base"
3
5
 
@@ -1,56 +1,60 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dir[File.join(__dir__, "operations/**/*.rb")].each do |file|
2
4
  require file
3
5
  end
4
6
 
5
7
  module ShinyJsonLogic
6
- class OperatorSolver
7
- def operation?(value)
8
- value.keys.any? { |key| solvers.key?(key.to_s) }
8
+ module OperatorSolver
9
+ SOLVERS = {
10
+ "var" => Operations::Var,
11
+ "missing" => Operations::Missing,
12
+ "missing_some" => Operations::MissingSome,
13
+ "==" => Operations::Equal,
14
+ "===" => Operations::StrictEqual,
15
+ "!=" => Operations::Different,
16
+ "!==" => Operations::StrictDifferent,
17
+ ">" => Operations::Greater,
18
+ ">=" => Operations::GreaterEqual,
19
+ "<" => Operations::Smaller,
20
+ "<=" => Operations::SmallerEqual,
21
+ "!" => Operations::Not,
22
+ "or" => Operations::Or,
23
+ "and" => Operations::And,
24
+ "in" => Operations::Inclusion,
25
+ "cat" => Operations::Concatenation,
26
+ "%" => Operations::Modulo,
27
+ "max" => Operations::Max,
28
+ "min" => Operations::Min,
29
+ "+" => Operations::Addition,
30
+ "*" => Operations::Product,
31
+ "-" => Operations::Subtraction,
32
+ "/" => Operations::Division,
33
+ "substr" => Operations::Substring,
34
+ "merge" => Operations::Merge,
35
+ "!!" => Operations::DoubleNot,
36
+ "val" => Operations::Val,
37
+ "??" => Operations::Coalesce,
38
+ "exists" => Operations::Exists,
39
+ "throw" => Operations::Throw,
40
+ "try" => Operations::Try,
41
+ "if" => Operations::If,
42
+ "?:" => Operations::If,
43
+ "filter" => Operations::Filter,
44
+ "map" => Operations::Map,
45
+ "reduce" => Operations::Reduce,
46
+ "all" => Operations::All,
47
+ "none" => Operations::None,
48
+ "some" => Operations::Some,
49
+ "preserve" => Operations::Preserve,
50
+ }.freeze
51
+
52
+ def self.solvers
53
+ SOLVERS
9
54
  end
10
55
 
11
- def solvers
12
- @@solvers ||= {
13
- "var" => Operations::Var,
14
- "missing" => Operations::Missing,
15
- "missing_some" => Operations::MissingSome,
16
- "==" => Operations::Equal,
17
- "===" => Operations::StrictEqual,
18
- "!=" => Operations::Different,
19
- "!==" => Operations::StrictDifferent,
20
- ">" => Operations::Greater,
21
- ">=" => Operations::GreaterEqual,
22
- "<" => Operations::Smaller,
23
- "<=" => Operations::SmallerEqual,
24
- "!" => Operations::Not,
25
- "or" => Operations::Or,
26
- "and" => Operations::And,
27
- "in" => Operations::Inclusion,
28
- "cat" => Operations::Concatenation,
29
- "%" => Operations::Modulo,
30
- "max" => Operations::Max,
31
- "min" => Operations::Min,
32
- "+" => Operations::Addition,
33
- "*" => Operations::Product,
34
- "-" => Operations::Subtraction,
35
- "/" => Operations::Division,
36
- "substr" => Operations::Substring,
37
- "merge" => Operations::Merge,
38
- "!!" => Operations::DoubleNot,
39
- "val" => Operations::Val,
40
- "??" => Operations::Coalesce,
41
- "exists" => Operations::Exists,
42
- "throw" => Operations::Throw,
43
- "try" => Operations::Try,
44
- "if" => Operations::If,
45
- "?:" => Operations::If,
46
- "filter" => Operations::Filter,
47
- "map" => Operations::Map,
48
- "reduce" => Operations::Reduce,
49
- "all" => Operations::All,
50
- "none" => Operations::None,
51
- "some" => Operations::Some,
52
- "preserve" => Operations::Preserve,
53
- }
56
+ def self.operation?(value)
57
+ value.keys.any? { |key| SOLVERS.key?(key.to_s) }
54
58
  end
55
59
  end
56
- end
60
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # https://jsonlogic.com/truthy.html
2
4
 
3
5
  module ShinyJsonLogic
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ShinyJsonLogic
2
- VERSION = "0.2.13"
4
+ VERSION = "0.2.15"
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "shiny_json_logic/version"
2
4
  require "shiny_json_logic/engine"
3
5
  require "shiny_json_logic/errors/base"
@@ -30,7 +32,7 @@ module ShinyJsonLogic
30
32
  operation, args = rule.first
31
33
 
32
34
  # Check if operation is known
33
- unless OperatorSolver.new.solvers.key?(operation.to_s)
35
+ unless OperatorSolver::SOLVERS.key?(operation.to_s)
34
36
  raise Errors::UnknownOperator
35
37
  end
36
38
 
data/results/ruby.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "totals": {
3
3
  "shiny_json_logic": {
4
- "passed": 1117,
5
- "total": 1126
4
+ "passed": 601,
5
+ "total": 601
6
6
  }
7
7
  }
8
8
  }
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.2.13
4
+ version: 0.2.15
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-09 00:00:00.000000000 Z
11
+ date: 2026-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -109,12 +109,7 @@ files:
109
109
  - ".github/workflows/ci.yml"
110
110
  - ".github/workflows/compat.yml"
111
111
  - ".gitignore"
112
- - ".idea/.gitignore"
113
- - ".idea/modules.xml"
114
- - ".idea/shiny_json_logic.iml"
115
- - ".idea/vcs.xml"
116
112
  - ".rspec"
117
- - ".travis.yml"
118
113
  - CHANGELOG.md
119
114
  - CONTRIBUTING.md
120
115
  - Gemfile
data/.idea/.gitignore DELETED
@@ -1,8 +0,0 @@
1
- # Default ignored files
2
- /shelf/
3
- /workspace.xml
4
- # Editor-based HTTP Client requests
5
- /httpRequests/
6
- # Datasource local storage ignored files
7
- /dataSources/
8
- /dataSources.local.xml
data/.idea/modules.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectModuleManager">
4
- <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/shiny_json_logic.iml" filepath="$PROJECT_DIR$/.idea/shiny_json_logic.iml" />
6
- </modules>
7
- </component>
8
- </project>
@@ -1,55 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="RUBY_MODULE" version="4">
3
- <component name="ModuleRunConfigurationManager">
4
- <shared />
5
- </component>
6
- <component name="NewModuleRootManager">
7
- <content url="file://$MODULE_DIR$">
8
- <sourceFolder url="file://$MODULE_DIR$/features" isTestSource="true" />
9
- <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
10
- <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
11
- </content>
12
- <orderEntry type="jdk" jdkName="ruby-2.6.8-p205" jdkType="RUBY_SDK" />
13
- <orderEntry type="sourceFolder" forTests="false" />
14
- <orderEntry type="library" scope="PROVIDED" name="bundler (v1.17.2, ruby-2.6.8-p205) [gem]" level="application" />
15
- <orderEntry type="library" scope="PROVIDED" name="byebug (v11.1.3, ruby-2.6.8-p205) [gem]" level="application" />
16
- <orderEntry type="library" scope="PROVIDED" name="coderay (v1.1.3, ruby-2.6.8-p205) [gem]" level="application" />
17
- <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.5.0, ruby-2.6.8-p205) [gem]" level="application" />
18
- <orderEntry type="library" scope="PROVIDED" name="method_source (v1.0.0, ruby-2.6.8-p205) [gem]" level="application" />
19
- <orderEntry type="library" scope="PROVIDED" name="pry (v0.14.1, ruby-2.6.8-p205) [gem]" level="application" />
20
- <orderEntry type="library" scope="PROVIDED" name="rake (v10.5.0, ruby-2.6.8-p205) [gem]" level="application" />
21
- <orderEntry type="library" scope="PROVIDED" name="rspec (v3.12.0, ruby-2.6.8-p205) [gem]" level="application" />
22
- <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.12.0, ruby-2.6.8-p205) [gem]" level="application" />
23
- <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.12.2, ruby-2.6.8-p205) [gem]" level="application" />
24
- <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.12.2, ruby-2.6.8-p205) [gem]" level="application" />
25
- <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.12.0, ruby-2.6.8-p205) [gem]" level="application" />
26
- </component>
27
- <component name="RakeTasksCache">
28
- <option name="myRootTask">
29
- <RakeTaskImpl id="rake">
30
- <subtasks>
31
- <RakeTaskImpl description="Build shiny_json_logic-0.1.0.gem into the pkg directory" fullCommand="build" id="build" />
32
- <RakeTaskImpl description="Remove any temporary products" fullCommand="clean" id="clean" />
33
- <RakeTaskImpl description="Remove any generated files" fullCommand="clobber" id="clobber" />
34
- <RakeTaskImpl description="Build and install shiny_json_logic-0.1.0.gem into system gems" fullCommand="install" id="install" />
35
- <RakeTaskImpl id="install">
36
- <subtasks>
37
- <RakeTaskImpl description="Build and install shiny_json_logic-0.1.0.gem into system gems without network access" fullCommand="install:local" id="local" />
38
- </subtasks>
39
- </RakeTaskImpl>
40
- <RakeTaskImpl description="Create tag v0.1.0 and build and push shiny_json_logic-0.1.0.gem to rubygems.org" fullCommand="release[remote]" id="release[remote]" />
41
- <RakeTaskImpl description="Run RSpec code examples" fullCommand="spec" id="spec" />
42
- <RakeTaskImpl description="" fullCommand="default" id="default" />
43
- <RakeTaskImpl description="" fullCommand="release" id="release" />
44
- <RakeTaskImpl id="release">
45
- <subtasks>
46
- <RakeTaskImpl description="" fullCommand="release:guard_clean" id="guard_clean" />
47
- <RakeTaskImpl description="" fullCommand="release:rubygem_push" id="rubygem_push" />
48
- <RakeTaskImpl description="" fullCommand="release:source_control_push" id="source_control_push" />
49
- </subtasks>
50
- </RakeTaskImpl>
51
- </subtasks>
52
- </RakeTaskImpl>
53
- </option>
54
- </component>
55
- </module>
data/.idea/vcs.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
- </component>
6
- </project>
data/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.8
7
- before_install: gem install bundler -v 1.17.2