shiny_json_logic 0.2.16 → 0.3.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -5
  5. data/lib/shiny_json_logic/comparisons/comparable.rb +27 -4
  6. data/lib/shiny_json_logic/engine.rb +1 -1
  7. data/lib/shiny_json_logic/numericals/min_max_collection.rb +9 -14
  8. data/lib/shiny_json_logic/numericals/numerify.rb +5 -5
  9. data/lib/shiny_json_logic/numericals/with_error_handling.rb +2 -0
  10. data/lib/shiny_json_logic/operations/addition.rb +5 -23
  11. data/lib/shiny_json_logic/operations/all.rb +1 -3
  12. data/lib/shiny_json_logic/operations/and.rb +3 -4
  13. data/lib/shiny_json_logic/operations/base.rb +13 -31
  14. data/lib/shiny_json_logic/operations/coalesce.rb +2 -2
  15. data/lib/shiny_json_logic/operations/concatenation.rb +4 -4
  16. data/lib/shiny_json_logic/operations/different.rb +2 -17
  17. data/lib/shiny_json_logic/operations/division.rb +6 -14
  18. data/lib/shiny_json_logic/operations/double_not.rb +3 -3
  19. data/lib/shiny_json_logic/operations/equal.rb +2 -16
  20. data/lib/shiny_json_logic/operations/exists.rb +4 -4
  21. data/lib/shiny_json_logic/operations/filter.rb +2 -4
  22. data/lib/shiny_json_logic/operations/greater.rb +2 -17
  23. data/lib/shiny_json_logic/operations/greater_equal.rb +2 -17
  24. data/lib/shiny_json_logic/operations/if.rb +5 -16
  25. data/lib/shiny_json_logic/operations/inclusion.rb +3 -3
  26. data/lib/shiny_json_logic/operations/iterable/base.rb +31 -61
  27. data/lib/shiny_json_logic/operations/max.rb +2 -4
  28. data/lib/shiny_json_logic/operations/merge.rb +3 -3
  29. data/lib/shiny_json_logic/operations/min.rb +2 -4
  30. data/lib/shiny_json_logic/operations/missing.rb +10 -10
  31. data/lib/shiny_json_logic/operations/missing_some.rb +7 -6
  32. data/lib/shiny_json_logic/operations/modulo.rb +6 -14
  33. data/lib/shiny_json_logic/operations/none.rb +1 -3
  34. data/lib/shiny_json_logic/operations/not.rb +2 -2
  35. data/lib/shiny_json_logic/operations/or.rb +3 -4
  36. data/lib/shiny_json_logic/operations/preserve.rb +8 -25
  37. data/lib/shiny_json_logic/operations/product.rb +7 -20
  38. data/lib/shiny_json_logic/operations/reduce.rb +24 -30
  39. data/lib/shiny_json_logic/operations/smaller.rb +2 -17
  40. data/lib/shiny_json_logic/operations/smaller_equal.rb +2 -17
  41. data/lib/shiny_json_logic/operations/some.rb +1 -3
  42. data/lib/shiny_json_logic/operations/strict_different.rb +6 -12
  43. data/lib/shiny_json_logic/operations/strict_equal.rb +6 -12
  44. data/lib/shiny_json_logic/operations/substring.rb +4 -4
  45. data/lib/shiny_json_logic/operations/subtraction.rb +7 -20
  46. data/lib/shiny_json_logic/operations/throw.rb +5 -7
  47. data/lib/shiny_json_logic/operations/try.rb +2 -3
  48. data/lib/shiny_json_logic/operations/val.rb +14 -22
  49. data/lib/shiny_json_logic/operations/var.rb +13 -15
  50. data/lib/shiny_json_logic/version.rb +1 -1
  51. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a4ebb694ae1ef43b04f2ef7a750bc102f202cc2e9efa6e0f43361bc66b82d4f
4
- data.tar.gz: e57b52493d8d60506c2ceb5c30bace49790bbd6fa5eb2e800f31fb4aae94bbd6
3
+ metadata.gz: df6cbb1873a1d4237a634ab972f9da4f2e1b56012f0e9353e34c723746f75655
4
+ data.tar.gz: b62ce7480cdbab13df690836b3c837b96b360d08fb6cd0c86ee8e743222234bc
5
5
  SHA512:
6
- metadata.gz: 2b336cd498e0286fe1a2f953fc43a8319b83b3792f4471ff8f78eed0dd7cb9174ade63f7fba91b7accca6eccedffb785fb413eae82de9d7f67611d5a5ea64959
7
- data.tar.gz: 3f76cf1ac0abea0a1e04a2b6ed2c1b468a028018a471afb20e88b4031555bdadaf0f917f179a84a0c258f4404bf9d61e7ad36a9e07c660a5ebd0177f7236e324
6
+ metadata.gz: cb846733714d95672c98d615c1474582e5516d13e02becbe13a9839d7571d7f2792235595777464b53c5e4173ea8af49d5d721d09283bfa72ade52f231bb74f7
7
+ data.tar.gz: 121d271417ace9b145dfc92861e7857ff8c22eb859a7a8d9f2d8ff6b37708a1ee3c55a22f60cf925c1826c41622012848a2a54dd3f4afc9b8084b4ae6424a8e1
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Changelog
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
+ ## [0.3.0] - 2026-02-21
5
+ ### Changed
6
+ - Refactors internal architecture to improve performance by removing instantiation of operations.
7
+
4
8
  ## [0.2.16] - 2026-02-21
5
9
  ### Changed
6
10
  - Removed simple delegator to check indifferent access in favour of key transformation . This improves performance and reduces memory usage.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shiny_json_logic (0.2.16)
4
+ shiny_json_logic (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -18,13 +18,12 @@ This gem focuses on predictable behavior, strict spec alignment, high compatibil
18
18
  - 🕰️ **Ruby 2.7+ 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
- - ⭐ **Only Ruby implementation supporting the latest standard operators** (`val`, `exists`, `??`, `try`, `throw`)
22
21
 
23
22
  If you want JSON Logic to *just work* in Ruby, this is the safe default.
24
23
 
25
24
  ---
26
25
  # Test it for yourself!
27
- Try it out in the sandbox at [jsonlogicruby.com](https://jsonlogicruby.com)
26
+ Try it out in the sandbox at [jsonlogicruby.com](https://jsonlogicruby.com/playground) or run the official test suite with `bin/test.sh` to see the compatibility for yourself.
28
27
 
29
28
  ---
30
29
 
@@ -158,9 +157,6 @@ Currently implemented operators include:
158
157
  ### Evaluation
159
158
  `preserve`✨
160
159
 
161
- 📌 **Note:**
162
- `val`, `exists`, `??`, `try`, `throw` and `preserve` are **only supported by ShinyJsonLogic** among Ruby implementations.
163
-
164
160
  See the [spec](https://jsonlogicruby.com/docs) for the full list of operators and their behavior.
165
161
 
166
162
  ---
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "shiny_json_logic/numericals/numerify"
4
+ require "shiny_json_logic/errors/not_a_number"
5
+ require "shiny_json_logic/errors/invalid_arguments"
4
6
 
5
7
  module ShinyJsonLogic
6
8
  module Comparisons
7
9
  module Comparable
8
- include Numericals::Numerify
9
-
10
- private
10
+ module_function
11
11
 
12
12
  def compare(a, b)
13
13
  return :nan if a.is_a?(Array) || a.is_a?(Hash) || b.is_a?(Array) || b.is_a?(Hash)
@@ -28,9 +28,32 @@ module ShinyJsonLogic
28
28
  return 0.0 if value == false
29
29
  return 1.0 if value == true
30
30
  return 0.0 if value.nil?
31
- return value.to_f if value.is_a?(String) && numeric_string?(value)
31
+ return value.to_f if value.is_a?(String) && Numericals::Numerify.numeric_string?(value)
32
32
  nil
33
33
  end
34
+
35
+ # Normalize numeric types for strict equality comparisons (=== semantics).
36
+ def cast(value)
37
+ value.is_a?(Numeric) ? value.to_f : value
38
+ end
39
+
40
+ # Shared loop for all chain-comparison operators.
41
+ # Yields the compare result for each consecutive pair; block returns true to continue, false to short-circuit.
42
+ # Returns true if all pairs pass, false otherwise. Raises on :nan or invalid args.
43
+ def compare_chain(rules, scope_stack)
44
+ operands = Utils::Array.wrap_nil(rules)
45
+ raise Errors::InvalidArguments if operands.length < 2
46
+
47
+ prev = Engine.call(operands[0], scope_stack)
48
+ operands[1..].each do |rule|
49
+ curr = Engine.call(rule, scope_stack)
50
+ result = compare(prev, curr)
51
+ raise Errors::NotANumber if result == :nan
52
+ return false unless yield(result)
53
+ prev = curr
54
+ end
55
+ true
56
+ end
34
57
  end
35
58
  end
36
59
  end
@@ -15,7 +15,7 @@ module ShinyJsonLogic
15
15
 
16
16
  return rule unless OPERATIONS.key?(operation_key)
17
17
 
18
- OPERATIONS.fetch(operation_key).new(args, scope_stack).call
18
+ OPERATIONS.fetch(operation_key).call(args, scope_stack)
19
19
  elsif rule.is_a?(Array)
20
20
  rule.map { |val| call(val, scope_stack) }
21
21
  else
@@ -5,29 +5,24 @@ require "shiny_json_logic/errors/invalid_arguments"
5
5
  module ShinyJsonLogic
6
6
  module Numericals
7
7
  module MinMaxCollection
8
- private
8
+ module_function
9
9
 
10
- def collect_numeric_values
11
- values = collect_values
10
+ def collect_numeric_values(rules, scope_stack)
11
+ values = collect_values(rules, scope_stack)
12
12
  raise Errors::InvalidArguments if values.empty?
13
13
  raise Errors::InvalidArguments unless values.all? { |v| v.is_a?(Numeric) }
14
14
  values
15
15
  end
16
16
 
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)
17
+ def collect_values(rules, scope_stack)
18
+ if Operations::Base.op?(rules)
19
+ evaluated = Engine.call(rules, scope_stack)
20
+ return Utils::Array.wrap_nil(evaluated)
23
21
  end
24
22
 
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)
28
23
  result = []
29
- wrap_nil(rules).each do |rule|
30
- result << evaluate(rule)
24
+ Utils::Array.wrap_nil(rules).each do |rule|
25
+ result << Engine.call(rule, scope_stack)
31
26
  end
32
27
  result
33
28
  end
@@ -3,7 +3,11 @@
3
3
  module ShinyJsonLogic
4
4
  module Numericals
5
5
  module Numerify
6
- private
6
+ # Regex to match valid numeric strings (integers, floats, scientific notation)
7
+ # Examples: "123", "-45.67", "+3.14", "1e10", "2.5E-3", ".5", "-.5"
8
+ NUMERIC_REGEX = /\A[+-]?(?:\d+\.?\d*|\d*\.?\d+)(?:[eE][+-]?\d+)?\z/
9
+
10
+ module_function
7
11
 
8
12
  def numerify(value)
9
13
  return value.to_f if value.is_a?(Numeric)
@@ -16,10 +20,6 @@ module ShinyJsonLogic
16
20
  raise TypeError, "Cannot convert #{value.inspect} to a number"
17
21
  end
18
22
 
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
-
23
23
  def numeric_string?(value)
24
24
  NUMERIC_REGEX.match?(value)
25
25
  end
@@ -7,6 +7,8 @@ require "shiny_json_logic/errors/invalid_arguments"
7
7
  module ShinyJsonLogic
8
8
  module Numericals
9
9
  module WithErrorHandling
10
+ module_function
11
+
10
12
  def safe_arithmetic(&block)
11
13
  result = yield
12
14
  if result.to_f.nan? || result == Float::INFINITY || result == -Float::INFINITY
@@ -7,36 +7,18 @@ require "shiny_json_logic/numericals/numerify"
7
7
  module ShinyJsonLogic
8
8
  module Operations
9
9
  class Addition < Base
10
- include Numericals::WithErrorHandling
11
- include Numericals::Numerify
10
+ extend Numericals::WithErrorHandling
12
11
 
13
- def call
12
+ def self.execute(rules, scope_stack)
14
13
  safe_arithmetic do
15
14
  result = 0.0
16
- count = 0
17
-
18
- each_operand do |num|
19
- count += 1
20
- result = result + num
15
+ Utils::Array.wrap_nil(rules).each do |rule|
16
+ val = Numericals::Numerify.numerify(evaluate(rule, scope_stack))
17
+ result += val.nil? ? 0 : val
21
18
  end
22
-
23
19
  result
24
20
  end
25
21
  end
26
-
27
- private
28
-
29
- def each_operand
30
- wrap_nil(rules).each do |rule|
31
- yield numerify(evaluate(rule))
32
- end
33
- end
34
-
35
- def numerify(value)
36
- val = super
37
- return 0 if val.nil?
38
- val
39
- end
40
22
  end
41
23
  end
42
24
  end
@@ -8,9 +8,7 @@ module ShinyJsonLogic
8
8
  class All < Iterable::Base
9
9
  raise_on_dynamic_args!
10
10
 
11
- private
12
-
13
- def on_after(results)
11
+ def self.on_after(results, _scope_stack)
14
12
  return false if results.empty?
15
13
 
16
14
  results.all? { |res| Truthy.call(res) }
@@ -7,17 +7,16 @@ require "shiny_json_logic/numericals/with_error_handling"
7
7
  module ShinyJsonLogic
8
8
  module Operations
9
9
  class And < Base
10
- include Numericals::WithErrorHandling
10
+ extend Numericals::WithErrorHandling
11
11
  raise_on_dynamic_args!
12
12
 
13
- def call
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 unless Truthy.call(result)
22
21
  end
23
22
  result
@@ -6,34 +6,21 @@ require "shiny_json_logic/utils/array"
6
6
  module ShinyJsonLogic
7
7
  module Operations
8
8
  class Base
9
- include Utils::Array
9
+ extend Utils::Array
10
10
 
11
- def initialize(rules, scope_stack)
12
- @scope_stack = scope_stack
13
- @dynamic_args = operation?(rules)
14
- @rules = pre_process(rules)
11
+ def self.call(rules, scope_stack)
12
+ execute(resolve_rules(rules, scope_stack), scope_stack)
15
13
  end
16
14
 
17
- def call
18
- raise NotImplementedError
19
- end
20
-
21
- protected
22
-
23
- attr_reader :scope_stack
24
- attr_accessor :rules
25
-
26
- # Access current data through scope_stack
27
- def data
28
- scope_stack.current
29
- end
30
-
31
- def evaluate(rule)
32
- Engine.call(rule, scope_stack)
15
+ def self.resolve_rules(rules, scope_stack)
16
+ dynamic = op?(rules)
17
+ rules = Engine.call(rules, scope_stack) if dynamic
18
+ raise Errors::InvalidArguments if dynamic && raise_on_dynamic_args?
19
+ rules
33
20
  end
34
21
 
35
- def dynamic_args?
36
- @dynamic_args && self.class.raise_on_dynamic_args?
22
+ def self.execute(_rules, _scope_stack)
23
+ raise NotImplementedError
37
24
  end
38
25
 
39
26
  def self.raise_on_dynamic_args!
@@ -44,17 +31,12 @@ module ShinyJsonLogic
44
31
  @raise_on_dynamic_args
45
32
  end
46
33
 
47
- private
48
-
49
- def pre_process(rules)
50
- return evaluate(rules) if operation?(rules)
51
-
52
- rules
34
+ def self.evaluate(rule, scope_stack)
35
+ Engine.call(rule, scope_stack)
53
36
  end
54
37
 
55
- def operation?(value)
38
+ def self.op?(value)
56
39
  return false unless value.is_a?(Hash) && !value.empty?
57
-
58
40
  OperatorSolver.operation?(value)
59
41
  end
60
42
  end
@@ -5,9 +5,9 @@ require "shiny_json_logic/operations/base"
5
5
  module ShinyJsonLogic
6
6
  module Operations
7
7
  class Coalesce < Base
8
- def call
8
+ def self.execute(rules, scope_stack)
9
9
  rules.each do |rule|
10
- result = evaluate(rule)
10
+ result = evaluate(rule, scope_stack)
11
11
  return result unless result.nil?
12
12
  end
13
13
  nil
@@ -5,11 +5,11 @@ require "shiny_json_logic/operations/base"
5
5
  module ShinyJsonLogic
6
6
  module Operations
7
7
  class Concatenation < Base
8
- def call
8
+ def self.execute(rules, scope_stack)
9
9
  result = []
10
- wrap_nil(rules).each do |rule|
11
- evaluated = evaluate(rule)
12
- wrap_nil(evaluated).each { |v| result << v.to_s }
10
+ Utils::Array.wrap_nil(rules).each do |rule|
11
+ evaluated = evaluate(rule, scope_stack)
12
+ Utils::Array.wrap_nil(evaluated).each { |v| result << v.to_s }
13
13
  end
14
14
  result.join
15
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 Different < Base
10
- include Numericals::WithErrorHandling
11
- include Comparisons::Comparable
12
9
  raise_on_dynamic_args!
13
10
 
14
- def call
15
- return handle_invalid_args if dynamic_args?
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 if 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
@@ -7,18 +7,19 @@ require "shiny_json_logic/numericals/numerify"
7
7
  module ShinyJsonLogic
8
8
  module Operations
9
9
  class Division < Base
10
- include Numericals::WithErrorHandling
11
- include Numericals::Numerify
10
+ extend Numericals::WithErrorHandling
12
11
 
13
- def call
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
  result = nil
18
17
  count = 0
19
18
 
20
19
  begin
21
- each_operand(operands) do |num|
20
+ operands.each do |rule|
21
+ evaluated = evaluate(rule, scope_stack)
22
+ num = Numericals::Numerify.numerify(evaluated)
22
23
  return handle_nan if num.nil?
23
24
  count += 1
24
25
  result = result.nil? ? num : result / num
@@ -33,15 +34,6 @@ module ShinyJsonLogic
33
34
 
34
35
  safe_arithmetic { final_result }
35
36
  end
36
-
37
- private
38
-
39
- def each_operand(operands)
40
- operands.each do |rule|
41
- evaluated = evaluate(rule)
42
- yield numerify(evaluated)
43
- end
44
- end
45
37
  end
46
38
  end
47
39
  end
@@ -6,9 +6,9 @@ require "shiny_json_logic/truthy"
6
6
  module ShinyJsonLogic
7
7
  module Operations
8
8
  class DoubleNot < Base
9
- def call
10
- value = wrap_nil(rules).first
11
- !!Truthy.call(evaluate(value))
9
+ def self.execute(rules, scope_stack)
10
+ value = Utils::Array.wrap_nil(rules).first
11
+ !!Truthy.call(evaluate(value, scope_stack))
12
12
  end
13
13
  end
14
14
  end
@@ -1,29 +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 Equal < Base
10
- include Numericals::WithErrorHandling
11
- include Comparisons::Comparable
12
9
  raise_on_dynamic_args!
13
10
 
14
- def call
15
- return handle_invalid_args if dynamic_args?
16
- operands = wrap_nil(rules)
17
- return handle_invalid_args if operands.length < 2
18
-
19
- first = evaluate(operands[0])
20
- operands[1..].each do |rule|
21
- curr = evaluate(rule)
22
- result = compare(first, curr)
23
- return handle_nan if result == :nan
24
- return false unless result == 0
25
- end
26
- true
11
+ def self.execute(rules, scope_stack)
12
+ Comparisons::Comparable.compare_chain(rules, scope_stack) { |r| r == 0 }
27
13
  end
28
14
  end
29
15
  end
@@ -5,11 +5,11 @@ require "shiny_json_logic/operations/base"
5
5
  module ShinyJsonLogic
6
6
  module Operations
7
7
  class Exists < Base
8
- def call
9
- current = data
8
+ def self.execute(rules, scope_stack)
9
+ current = scope_stack.current
10
10
 
11
- wrap_nil(rules).each do |rule|
12
- segment = evaluate(rule)
11
+ Utils::Array.wrap_nil(rules).each do |rule|
12
+ segment = evaluate(rule, scope_stack)
13
13
  return false unless current.key?(segment)
14
14
  current = current[segment]
15
15
  end
@@ -9,13 +9,11 @@ module ShinyJsonLogic
9
9
  raise_on_nil_filter!
10
10
  raise_on_dynamic_args!
11
11
 
12
- private
13
-
14
- def on_each(item)
12
+ def self.on_each(item, filter, scope_stack)
15
13
  Truthy.call(Engine.call(filter, scope_stack)) ? item : nil
16
14
  end
17
15
 
18
- def on_after(results)
16
+ def self.on_after(results, _scope_stack)
19
17
  results.compact
20
18
  end
21
19
  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 Greater < Base
10
- include Numericals::WithErrorHandling
11
- include Comparisons::Comparable
12
9
  raise_on_dynamic_args!
13
10
 
14
- def call
15
- return handle_invalid_args if dynamic_args?
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 GreaterEqual < Base
10
- include Numericals::WithErrorHandling
11
- include Comparisons::Comparable
12
9
  raise_on_dynamic_args!
13
10
 
14
- def call
15
- return handle_invalid_args if dynamic_args?
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
@@ -7,34 +7,23 @@ require "shiny_json_logic/numericals/with_error_handling"
7
7
  module ShinyJsonLogic
8
8
  module Operations
9
9
  class If < Base
10
- include Numericals::WithErrorHandling
10
+ extend Numericals::WithErrorHandling
11
11
 
12
- # Skip pre_process - spec requires static array, dynamic args should error
13
- def initialize(rules, scope_stack)
14
- @rules = rules
15
- @scope_stack = scope_stack
16
- end
17
-
18
- def call
12
+ def self.call(rules, scope_stack)
13
+ # Skip pre_process - spec requires static array, dynamic args should error
19
14
  return handle_invalid_args unless rules.is_a?(Array)
20
15
 
21
16
  rules.each_slice(2) do |condition_rule, value_rule|
22
- condition_result = evaluate(condition_rule)
17
+ condition_result = Engine.call(condition_rule, scope_stack)
23
18
  return condition_result if value_rule.nil?
24
19
 
25
20
  next unless Truthy.call(condition_result)
26
21
 
27
- return evaluate(value_rule)
22
+ return Engine.call(value_rule, scope_stack)
28
23
  end
29
24
 
30
25
  nil
31
26
  end
32
-
33
- private
34
-
35
- def evaluate(rule)
36
- Engine.call(rule, scope_stack)
37
- end
38
27
  end
39
28
  end
40
29
  end
@@ -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 call
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