json-logic-rb 0.1.1 → 0.1.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +42 -49
  3. data/lib/json_logic/operation.rb +1 -1
  4. data/lib/json_logic/operations/add.rb +1 -1
  5. data/lib/json_logic/operations/all.rb +1 -1
  6. data/lib/json_logic/operations/and.rb +1 -1
  7. data/lib/json_logic/operations/bool_cast.rb +1 -1
  8. data/lib/json_logic/operations/cat.rb +1 -1
  9. data/lib/json_logic/operations/div.rb +1 -1
  10. data/lib/json_logic/operations/equal.rb +1 -1
  11. data/lib/json_logic/operations/filter.rb +1 -1
  12. data/lib/json_logic/operations/gt.rb +1 -1
  13. data/lib/json_logic/operations/gte.rb +1 -1
  14. data/lib/json_logic/operations/if.rb +1 -1
  15. data/lib/json_logic/operations/in.rb +1 -1
  16. data/lib/json_logic/operations/lt.rb +1 -1
  17. data/lib/json_logic/operations/lte.rb +1 -1
  18. data/lib/json_logic/operations/map.rb +1 -1
  19. data/lib/json_logic/operations/max.rb +1 -1
  20. data/lib/json_logic/operations/merge.rb +1 -1
  21. data/lib/json_logic/operations/min.rb +1 -1
  22. data/lib/json_logic/operations/missing.rb +1 -1
  23. data/lib/json_logic/operations/missing_some.rb +1 -1
  24. data/lib/json_logic/operations/mod.rb +1 -1
  25. data/lib/json_logic/operations/mul.rb +1 -1
  26. data/lib/json_logic/operations/none.rb +1 -1
  27. data/lib/json_logic/operations/not.rb +1 -1
  28. data/lib/json_logic/operations/not_equal.rb +1 -1
  29. data/lib/json_logic/operations/or.rb +1 -1
  30. data/lib/json_logic/operations/reduce.rb +1 -1
  31. data/lib/json_logic/operations/some.rb +1 -1
  32. data/lib/json_logic/operations/strict_equal.rb +3 -3
  33. data/lib/json_logic/operations/strict_not_equal.rb +1 -1
  34. data/lib/json_logic/operations/sub.rb +1 -1
  35. data/lib/json_logic/operations/substr.rb +1 -1
  36. data/lib/json_logic/operations/ternary.rb +1 -1
  37. data/lib/json_logic/operations/var.rb +1 -1
  38. data/lib/json_logic/registry.rb +1 -1
  39. data/lib/json_logic/semantics.rb +1 -7
  40. data/lib/json_logic/version.rb +1 -1
  41. data/lib/json_logic.rb +13 -3
  42. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc614e1da0fa7f6a40304c0e988508dc71f67b2f65ded67e3ecdbf5be6b4c2ce
4
- data.tar.gz: 2e80d861339668970a908e3ffbc6f3ea7562daa51850ce9ce90a1eb35b6ca598
3
+ metadata.gz: 975d191c041cd7afd3e3ab977d01944e00693ec7320e6418ae312d71afa67d7f
4
+ data.tar.gz: 9b871c8f3b53fbc5cf3e2dbd180a556e5815940c536da6e2c248bf8b66c9be8d
5
5
  SHA512:
6
- metadata.gz: b28f05aeb82f7163634d49b7a1eec0e3988b68bd6981111f8ee94de43fc000293730740c116dcb3d757500e58c22672ef1b913199b4d1a901fd50c18fee0963f
7
- data.tar.gz: f724dda9f6f0237144fac1255c9b0b20a848decb6981d6a3c19606375a5611c8367bed214e987ecb88b38c9cdaed1e73478ff17052a055b4b0249dfd1ff76bf4
6
+ metadata.gz: eef9bc4ce561c092cc5bd7885b9f69051e4aa0712dd15e93c92f4dd32c177570472a401e7bdce65565cee4ee8b80e3ebc3afaa46a0fab91cb1f730c83f0e1a83
7
+ data.tar.gz: fce35e13727e2d30e827c787c5543eb13005c38a59e44abcb8a340b486d1c814d4367d297dc20826b845dd7da98c193b2fa1bf0a521d6aa70bff2847da51eb6c
data/README.md CHANGED
@@ -55,7 +55,7 @@ There are **two types of operations** in this implementation: Default Operations
55
55
 
56
56
  ### 1. Default Operations
57
57
 
58
- For **Default Operations**, the engine **evaluates all arguments first** and then calls the operator with the **resulting Ruby values**.
58
+ For **Default Operations**, the engine **evaluates all arguments first** and then calls the operator with the **resulting Ruby values**.
59
59
  This matches the reference behavior for arithmetic, comparisons, string operations, and other pure operations that do not control evaluation order.
60
60
 
61
61
  **Groups and references:**
@@ -70,16 +70,16 @@ Some operations must control **whether** and **when** their arguments are evalua
70
70
 
71
71
  **Groups and references:**
72
72
 
73
- - **Branching / boolean control** — `if`, `?:`, `and`, `or`, `var`
73
+ - **Branching / boolean control** — `if`, `?:`, `and`, `or`, `var`
74
74
  [Logic & boolean operations](https://jsonlogic.com/operations.html#logic-and-boolean-operations) • [Truthiness](https://jsonlogic.com/truthy.html)
75
75
 
76
- - **Enumerable operators** — `map`, `filter`, `reduce`, `all`, `none`, `some`
76
+ - **Enumerable operators** — `map`, `filter`, `reduce`, `all`, `none`, `some`
77
77
  [Array operations](https://jsonlogic.com/operations.html#array-operations)
78
78
 
79
79
  **How enumerable per-item evaluation works:**
80
80
 
81
- 1. The first argument is a rule that returns the list of items — evaluated **once** to a Ruby array.
82
- 2. The second argument is the per-item rule — evaluated **for each item** with that item as the **current root**.
81
+ 1. The first argument is a rule that returns the list of items — evaluated **once** to a Ruby array.
82
+ 2. The second argument is the per-item rule — evaluated **for each item** with that item as the **current root**.
83
83
  3. For `reduce`, the current item is also available as `"current"`, and the running total as `"accumulator"`.
84
84
 
85
85
 
@@ -131,7 +131,7 @@ Below is a list that mirrors the sections on [jsonlogic.com/operations.html](htt
131
131
  | `var` | ✅ |
132
132
  | `missing` | ✅ |
133
133
  | `missing_some` | ✅ |
134
- |[Logic and Boolean Operations](https://jsonlogic.com/operations.html#logic-and-boolean-operations])
134
+ |[Logic and Boolean Operations](https://jsonlogic.com/operations.html#logic-and-boolean-operations])
135
135
  | `if` | ✅ |
136
136
  | `==` | ✅ |
137
137
  | `===` | ✅ |
@@ -171,16 +171,43 @@ Below is a list that mirrors the sections on [jsonlogic.com/operations.html](htt
171
171
 
172
172
  Need a custom operation? It’s straightforward.
173
173
 
174
- ### 1) Pick the operation type
174
+ ### Quick register a Proc or Lambda
175
+
176
+ Register little anonymous functions, by passing a Proc or Lambda.
177
+
178
+ ```ruby
179
+ JsonLogic.add_operation("times2") { |(value), _| value.to_i * 2 }
180
+ ```
181
+
182
+ Once the function added, you can use it in your logic.
183
+
184
+ ```ruby
185
+ JsonLogic.apply({ "times2" => [21] })
186
+ # => 42
187
+ ```
188
+
189
+ Is useful for rapid prototyping with minimal boilerplate;
190
+ Later you can “promote” it into a full class or use additional features.
191
+
192
+
193
+ ### 1) Pick the Operation type
175
194
  Choose one of:
176
195
  - **Default**
177
196
  ```ruby
178
197
  class JsonLogic::Operations::StartsWith < JsonLogic::Operation; end
179
198
  ```
199
+ For anonymous functions:
200
+ ```ruby
201
+ JsonLogic.add_operation("starts_with", lazy: false) do; end
202
+ ```
180
203
  - **Lazy**
181
204
  ```ruby
182
205
  class JsonLogic::Operations::StartsWith < JsonLogic::LazyOperation; end
183
206
  ```
207
+ For anonymous functions:
208
+ ```ruby
209
+ JsonLogic.add_operation("starts_with", lazy: true) do; end
210
+ ```
184
211
 
185
212
  See [§How](#how) for details.
186
213
 
@@ -197,17 +224,17 @@ See [§JsonLogic Semantic](#jsonlogic-semantic) for details.
197
224
  ### 3) Create an Operation and provide a machine name
198
225
 
199
226
  Operation methods use a consistent call shape.
200
-
227
+
201
228
  - The first parameter is the **array of operator arguments**.
202
229
  - The second is the current **data**.
203
230
 
204
-
231
+
205
232
 
206
233
  Thanks to Ruby’s destructuring, you can unpack the argument array right in the method signature.
207
234
 
208
235
  ```ruby
209
236
  class JsonLogic::Operations::StartsWith < JsonLogic::Operation
210
- def self.op_name = "starts_with"
237
+ def self.name = "starts_with"
211
238
  def call((str, prefix), _data)
212
239
  # str, prefix are ALREADY evaluated to Ruby values
213
240
  str.to_s.start_with?(prefix.to_s)
@@ -227,45 +254,11 @@ After registration, use it in rules:
227
254
  { "starts_with": [ { "var": "email" }, "admin@" ] }
228
255
  ```
229
256
 
230
- ### Alternative — register a Proc/Lambda
231
257
 
232
- The public API is class‑oriented, but **technically** you can express an Operations as a `Proc`/`Lambda` and register it through a little anonymous functions.
233
-
234
- DSL to register callables:
235
-
236
- ```ruby
237
- module JsonLogic
238
- module DSL
239
- def self.register_proc(name, lazy: false, &block)
240
- base = lazy ? JsonLogic::LazyOperation : JsonLogic::Operation
241
- klass = Class.new(base) do
242
- define_singleton_method(:op_name) { name.to_s }
243
- define_method(:call) { |args, data| block.call(args, data) }
244
- end
245
- JsonLogic::Engine.default.registry.register(klass)
246
- klass
247
- end
248
- end
249
- end
250
- ```
251
-
252
-
253
-
254
- Is useful for rapid prototyping with minimal boilerplate;
255
-
256
-
257
-
258
- ```ruby
259
- JsonLogic::DSL.register_proc("starts_with") do |(str, prefix), _data|
260
- str.to_s.start_with?(prefix.to_s)
261
- end
262
- ```
263
-
264
- Later you can “promote” the it into a full class.
265
258
 
266
259
  ## JsonLogic Semantic
267
260
 
268
- All supported Operations follow JsonLogic semantics.
261
+ All supported Operations follow JsonLogic semantics.
269
262
 
270
263
  ### Comparisons
271
264
  As JsonLogic primary developed in JavaScript it inherits JavaScript's type coercion in build-in Operations. JsonLogic (JS‑style) comparisons coerce types; Ruby does not.
@@ -293,7 +286,7 @@ using JsonLogic::Semantics
293
286
 
294
287
  ### Truthiness
295
288
 
296
- JsonLogic’s truthiness differs from Ruby’s (see <https://jsonlogic.com/truthy.html>).
289
+ JsonLogic’s truthiness differs from Ruby’s (see <https://jsonlogic.com/truthy.html>).
297
290
  In Ruby, only `false` and `nil` are falsey. In JsonLogic empty strings and empty arrays are also falsey.
298
291
 
299
292
  **In Ruby:**
@@ -318,18 +311,18 @@ truthy?([])
318
311
 
319
312
  Optional: quick self-test
320
313
 
321
-
314
+
322
315
 
323
316
  ```bash
324
317
  ruby test/selftest.rb
325
318
  ```
326
319
 
327
-
320
+
328
321
  Official test suite
329
322
 
330
323
  1. Fetch the official suite
331
324
 
332
-
325
+
333
326
 
334
327
  ```bash
335
328
  mkdir -p spec/tmp
@@ -4,7 +4,7 @@ module JsonLogic
4
4
  class Operation
5
5
  include Semantics
6
6
 
7
- def self.op_name = nil
7
+ def self.name = nil
8
8
 
9
9
  def self.values_only? = true
10
10
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Add < JsonLogic::Operation
4
- def self.op_name = "+"
4
+ def self.name = "+"
5
5
 
6
6
  def call(values, _data)
7
7
  values.map!(&:to_f).sum
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::All < JsonLogic::EnumerableOperation
6
- def self.op_name = "all"
6
+ def self.name = "all"
7
7
 
8
8
  def call(args, data)
9
9
  items, rule_applied_to_each_item = resolve_items_and_per_item_rule(args, data)
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::And < JsonLogic::LazyOperation
6
- def self.op_name = "and"
6
+ def self.name = "and"
7
7
 
8
8
  def call(args, data)
9
9
  last = nil
@@ -2,7 +2,7 @@
2
2
 
3
3
  using JsonLogic::Semantics
4
4
  class JsonLogic::Operations::BoolCast < JsonLogic::Operation
5
- def self.op_name = "!!"
5
+ def self.name = "!!"
6
6
 
7
7
  def call((a), _data)
8
8
  !!a
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Cat < JsonLogic::Operation
4
- def self.op_name = "cat"
4
+ def self.name = "cat"
5
5
 
6
6
  def call(values, _data) = values.map!(&:to_s).join
7
7
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Div < JsonLogic::Operation
4
- def self.op_name = "/"
4
+ def self.name = "/"
5
5
 
6
6
  def call((a,b), _data) = (b.to_f == 0 ? nil : a.to_f / b.to_f)
7
7
  end
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::Equal < JsonLogic::Operation
6
- def self.op_name = "=="
6
+ def self.name = "=="
7
7
 
8
8
  def call((a,b), _data)
9
9
  a == b
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::Filter < JsonLogic::EnumerableOperation
6
- def self.op_name = "filter"
6
+ def self.name = "filter"
7
7
 
8
8
  def call(args, data)
9
9
  items, rule_applied_to_each_item = resolve_items_and_per_item_rule(args, data)
@@ -3,6 +3,6 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::GT < JsonLogic::Operation
6
- def self.op_name = ">"
6
+ def self.name = ">"
7
7
  def call((a,b), _data) = a > b
8
8
  end
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::GTE < JsonLogic::Operation
6
- def self.op_name = ">="
6
+ def self.name = ">="
7
7
 
8
8
  def call((a,b), _data)
9
9
  a >= b
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::If < JsonLogic::LazyOperation
6
- def self.op_name = "if"
6
+ def self.name = "if"
7
7
 
8
8
  def call(args, data)
9
9
  i = 0
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::In < JsonLogic::Operation
4
- def self.op_name = "in"
4
+ def self.name = "in"
5
5
 
6
6
  def call((a,b), _data) = (b.respond_to?(:include?) && b.include?(a))
7
7
  end
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::LT < JsonLogic::Operation
6
- def self.op_name = "<"
6
+ def self.name = "<"
7
7
 
8
8
  def call(values, _data)
9
9
  return values[0] < values[1] if values.size == 2
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::LTE < JsonLogic::Operation
6
- def self.op_name = "<="
6
+ def self.name = "<="
7
7
 
8
8
  def call(values, _data)
9
9
  return values[0] <= values[1] if values.size == 2
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Map < JsonLogic::EnumerableOperation
4
- def self.op_name = "map"
4
+ def self.name = "map"
5
5
 
6
6
  def call(args, data)
7
7
  items, rule_applied_to_each_item = resolve_items_and_per_item_rule(args, data)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Max < JsonLogic::Operation
4
- def self.op_name = "max"
4
+ def self.name = "max"
5
5
 
6
6
  def call(values, _data) = values.max
7
7
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Merge < JsonLogic::Operation
4
- def self.op_name = "merge"
4
+ def self.name = "merge"
5
5
  def call(values, _data)
6
6
  values.flat_map { |v| v.is_a?(Array) ? v : [v] }
7
7
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Min < JsonLogic::Operation
4
- def self.op_name = "min"
4
+ def self.name = "min"
5
5
 
6
6
  def call(values, _data) = values.min
7
7
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Missing < JsonLogic::Operation
4
- def self.op_name = "missing"
4
+ def self.name = "missing"
5
5
 
6
6
  def call(values, data)
7
7
  keys =
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::MissingSome < JsonLogic::Operation
4
- def self.op_name = "missing_some"
4
+ def self.name = "missing_some"
5
5
 
6
6
  def call((min_ok, list), data)
7
7
  arr = list.is_a?(Array) ? list : Array(list)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Mod < JsonLogic::Operation
4
- def self.op_name = "%"
4
+ def self.name = "%"
5
5
 
6
6
  def call((a,b), _data) = a.to_f % b.to_f
7
7
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Mul < JsonLogic::Operation
4
- def self.op_name = "*"
4
+ def self.name = "*"
5
5
  def call(values, _data) = values.map!(&:to_f).inject(1){|m,v| m * v }
6
6
  end
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::None < JsonLogic::EnumerableOperation
6
- def self.op_name = "none"
6
+ def self.name = "none"
7
7
 
8
8
  def call(args, data)
9
9
  items, rule_applied_to_each_item = resolve_items_and_per_item_rule(args, data)
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::Not < JsonLogic::Operation
6
- def self.op_name = "!";
6
+ def self.name = "!";
7
7
 
8
8
  def call((a), _data) = !a
9
9
  end
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::NotEqual < JsonLogic::Operation
6
- def self.op_name = "!="
6
+ def self.name = "!="
7
7
 
8
8
  def call((a,b), _data)
9
9
  !(a == b)
@@ -2,7 +2,7 @@
2
2
 
3
3
  using JsonLogic::Semantics
4
4
  class JsonLogic::Operations::Or < JsonLogic::LazyOperation
5
- def self.op_name = "or"
5
+ def self.name = "or"
6
6
 
7
7
  def call(args, data)
8
8
  args.each do |a|
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Reduce < JsonLogic::EnumerableOperation
4
- def self.op_name = "reduce"
4
+ def self.name = "reduce"
5
5
 
6
6
  def call(args, data)
7
7
  rule_that_returns_items, step_rule_applied_per_item, rule_that_returns_initial_accumulator = args
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::Some < JsonLogic::EnumerableOperation
6
- def self.op_name = "some"
6
+ def self.name = "some"
7
7
 
8
8
  def call(args, data)
9
9
  items, rule_applied_to_each_item = resolve_items_and_per_item_rule(args, data)
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::StrictEqual < JsonLogic::Operation
4
- def self.op_name = "==="
5
-
6
- def call((a,b), _data)
4
+ def self.name = "==="
5
+
6
+ def call((a,b), _data)
7
7
  a === b
8
8
  end
9
9
  end
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::StrictNotEqual < JsonLogic::Operation
6
- def self.op_name = "!=="
6
+ def self.name = "!=="
7
7
 
8
8
  def call((a,b), _data)
9
9
  !(a === b)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Sub < JsonLogic::Operation
4
- def self.op_name = "-"
4
+ def self.name = "-"
5
5
  def call(values, _data) = (values.size == 1 ? -values[0].to_f : values[0].to_f - values[1].to_f)
6
6
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Substr < JsonLogic::Operation
4
- def self.op_name = "substr"
4
+ def self.name = "substr"
5
5
 
6
6
  def call(values, _data)
7
7
  s, i, len = values
@@ -3,7 +3,7 @@
3
3
  using JsonLogic::Semantics
4
4
 
5
5
  class JsonLogic::Operations::Ternary < JsonLogic::LazyOperation
6
- def self.op_name = "?:"
6
+ def self.name = "?:"
7
7
 
8
8
  def call((cond_rule, then_rule, else_rule), data)
9
9
  if !!JsonLogic.apply(cond_rule, data)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsonLogic::Operations::Var < JsonLogic::Operation
4
- def self.op_name = "var";
4
+ def self.name = "var";
5
5
  def self.values_only? = false
6
6
 
7
7
  def call((path_rule, fallback_rule), data)
@@ -7,7 +7,7 @@ module JsonLogic
7
7
  end
8
8
 
9
9
  def register(op_class)
10
- name = op_class.op_name or raise ArgumentError, 'op_name missing'
10
+ name = op_class.name or raise ArgumentError, 'name missing'
11
11
  @map[name.to_s] = op_class
12
12
  self
13
13
  end
@@ -86,7 +86,7 @@ module JsonLogic
86
86
  end
87
87
  end
88
88
 
89
- [String, Integer, Float].each do |klass|
89
+ [String, Integer, Float, NilClass, Array, TrueClass, FalseClass].each do |klass|
90
90
  refine klass do
91
91
  def ==(other) = JsonLogic::Semantics.eq(self, other)
92
92
  def >(other) = (c = JsonLogic::Semantics.cmp(self, other)) && c == 1
@@ -95,11 +95,5 @@ module JsonLogic
95
95
  def <=(other) = (c = JsonLogic::Semantics.cmp(self, other)) && (c == -1 || c == 0)
96
96
  end
97
97
  end
98
-
99
- [Array, TrueClass, FalseClass, NilClass].each do |klass|
100
- refine klass do
101
- def ==(other) = JsonLogic::Semantics.eq(self, other)
102
- end
103
- end
104
98
  end
105
99
  end
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module JsonLogic; VERSION = '0.1.1'; end
3
+ module JsonLogic; VERSION = '0.1.3'; end
data/lib/json_logic.rb CHANGED
@@ -14,10 +14,10 @@ module JsonLogic
14
14
  end
15
15
 
16
16
 
17
- # Load operation classes (each file defines one class with .op_name)
17
+ # Load operation classes (each file defines one class with .name)
18
18
  Dir[File.join(__dir__, 'json_logic', 'operations', '*.rb')].sort.each { |f| require f }
19
19
 
20
- # Auto-register all operation classes with .op_name
20
+ # Auto-register all operation classes with .name
21
21
  module JsonLogic
22
22
  module Loader
23
23
  module_function
@@ -25,7 +25,7 @@ module JsonLogic
25
25
  def register_all!(registry)
26
26
  ObjectSpace.each_object(Class) do |klass|
27
27
  next unless klass < JsonLogic::Operation
28
- next unless klass.respond_to?(:op_name) && klass.op_name && !klass.op_name.to_s.empty?
28
+ next unless klass.respond_to?(:name) && klass.name && !klass.name.to_s.empty?
29
29
 
30
30
  registry.register(klass)
31
31
  end
@@ -36,6 +36,16 @@ module JsonLogic
36
36
  def apply(rule, data = nil)
37
37
  Engine.default.evaluate(rule, data)
38
38
  end
39
+
40
+ def add_operation(name, lazy: false, &block)
41
+ base = lazy ? JsonLogic::LazyOperation : JsonLogic::Operation
42
+ klass = Class.new(base) do
43
+ define_singleton_method(:name) { name.to_s }
44
+ define_method(:call) { |args, data| block.call(args, data) }
45
+ end
46
+ JsonLogic::Engine.default.registry.register(klass)
47
+ klass
48
+ end
39
49
  end
40
50
  end
41
51
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-logic-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tavrel Kate