lex-conditioner 0.2.5 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d7c725a33a160829135b9b2269533484ab211ee5654951d929ce49dbfffcbbe
4
- data.tar.gz: c4b994cf4d00aac64316b4023b63fb02cb420288fc0eb310868c3ad9a49ec856
3
+ metadata.gz: a8f0f6e6d047004004fc22bbbc5e59600a19a49c0456cd469e8abfbf2182d12a
4
+ data.tar.gz: 9511f9d436244571f12bc15b587c028c2692c0fff54ed81ea5caaf1a59948676
5
5
  SHA512:
6
- metadata.gz: 15f92eb0f63890df974300c03c72c082228b61ad165c29da251a6955060f98bbbdb25bf80d2841f2c284a3deeb6c5e099e826747e85e4a74ce9d4fd8eca83acb
7
- data.tar.gz: 4a41130e68f0a464e48ff540fc442b91c7f2cef10aa0ad165484b43cf6895623f6df07be4ea8f856de6b865a8ba3d197a3771f4cc781e8f19608c8d6cce6413a
6
+ metadata.gz: 5a86d76e674865fa293c3dff60e8a7a7f22f6dbf632d1a336c9f2fdbc88b47a68f727408a1e358d43571b904ac53612c226c6819caaa6d1354d8b9909a61ff4b
7
+ data.tar.gz: bbb2646ca44322974146f11bef9c9012d5363838645f29f8d12d77b7b685d725b91891d97644baeccbdcbbb30f445107dfc46098cad35d2dadb90e052901c1bb
@@ -0,0 +1,16 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+
7
+ jobs:
8
+ ci:
9
+ uses: LegionIO/.github/.github/workflows/ci.yml@main
10
+
11
+ release:
12
+ needs: ci
13
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
14
+ uses: LegionIO/.github/.github/workflows/release.yml@main
15
+ secrets:
16
+ rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ Gemfile.lock
data/.rubocop.yml CHANGED
@@ -1,33 +1,49 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.4
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+
1
6
  Layout/LineLength:
2
- Max: 120
7
+ Max: 160
8
+ Layout/SpaceAroundEqualsInParameterDefault:
9
+ EnforcedStyle: space
10
+ Layout/HashAlignment:
11
+ EnforcedHashRocketStyle: table
12
+ EnforcedColonStyle: table
13
+
3
14
  Metrics/MethodLength:
4
- Max: 30
15
+ Max: 50
5
16
  Metrics/ClassLength:
6
17
  Max: 1500
18
+ Metrics/ModuleLength:
19
+ Max: 1500
7
20
  Metrics/BlockLength:
8
- Max: 50
21
+ Max: 40
22
+ Exclude:
23
+ - 'spec/**/*'
9
24
  Metrics/AbcSize:
10
- Max: 20
25
+ Max: 60
11
26
  Metrics/CyclomaticComplexity:
12
- Max: 20
27
+ Max: 15
13
28
  Metrics/PerceivedComplexity:
14
- Max: 20
15
- Layout/SpaceAroundEqualsInParameterDefault:
16
- EnforcedStyle: space
17
- Style/SymbolArray:
18
- Enabled: true
19
- Layout/HashAlignment:
20
- EnforcedHashRocketStyle: table
21
- EnforcedColonStyle: table
29
+ Max: 17
30
+ Metrics/ParameterLists:
31
+ Enabled: false
32
+
22
33
  Style/Documentation:
23
34
  Enabled: false
24
- AllCops:
25
- TargetRubyVersion: 2.5
26
- NewCops: enable
27
- SuggestExtensions: false
35
+ Style/SymbolArray:
36
+ Enabled: true
28
37
  Style/FrozenStringLiteralComment:
29
- Enabled: false
38
+ Enabled: true
39
+ EnforcedStyle: always
40
+
30
41
  Naming/FileName:
31
42
  Enabled: false
32
- Style/ClassAndModuleChildren:
33
- Enabled: false
43
+ Naming/PredicateMethod:
44
+ Enabled: false
45
+ Naming/PredicatePrefix:
46
+ Enabled: false
47
+
48
+ Gemspec/DevelopmentDependencies:
49
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,27 @@
1
+ # Changelog
2
+
3
+ ## [0.3.1] - 2026-03-22
4
+
5
+ ### Changed
6
+ - Migrated to sub-gem helpers (Tier 1): added runtime dependencies on legion-cache >= 1.3.11, legion-crypt >= 1.4.9, legion-data >= 1.4.17, legion-json >= 1.2.1, legion-logging >= 1.3.2, legion-settings >= 1.3.14, legion-transport >= 1.3.9
7
+ - Replaced direct `Legion::Logging` calls in runner with `log` helper method via `Helpers::Lex` (includes `Legion::Logging::Helper`)
8
+ - Updated spec_helper to use real sub-gem helpers with `Helpers::Lex` module and actor stubs; removed inline Legion::Logging and Legion::JSON stubs
9
+ - Updated runner spec to remove framework stubs covered by spec_helper; added scoped `Helpers::Task`, `Transport::Messages::SubTask`, and `Exception::MissingArgument` stubs
10
+
11
+ ## [0.3.0] - 2026-03-17
12
+
13
+ ### Added
14
+ - 14 new operators: `greater_than`, `less_than`, `greater_or_equal`, `less_or_equal`, `between` (numeric); `contains`, `starts_with`, `ends_with`, `matches` (string); `in_set`, `not_in_set`, `empty`, `not_empty`, `size_equal` (collection) — 23 total
15
+ - Structured condition explanation via `Condition#explain` returning per-rule results with `fact`, `operator`, `value`, `actual`, and `result`
16
+ - Standalone `Client` class for framework-independent evaluation
17
+ - SimpleCov coverage reporting
18
+ - Modern packaging: grouped test dependencies, `require_relative` in gemspec, `rubocop-rspec`
19
+
20
+ ### Fixed
21
+ - `Comparator.false?` returning `nil` instead of `false` for truthy values
22
+ - Typo `funciton_id` corrected to `function_id` in runner `send_task` whitelist
23
+
24
+ ## [0.2.5] - 2026-03-13
25
+
26
+ ### Added
27
+ - Initial release
data/CLAUDE.md ADDED
@@ -0,0 +1,135 @@
1
+ # lex-conditioner: Conditional Rule Engine for LegionIO
2
+
3
+ **Repository Level 3 Documentation**
4
+ - **Parent**: `/Users/miverso2/rubymine/legion/extensions-core/CLAUDE.md`
5
+ - **Grandparent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
6
+
7
+ ## Purpose
8
+
9
+ Legion Extension that applies conditional statements to tasks within relationships. Evaluates JSON-based rules against task payloads to determine whether downstream tasks should execute, enabling branching logic in task chains.
10
+
11
+ **GitHub**: https://github.com/LegionIO/lex-conditioner
12
+ **License**: MIT
13
+ **Version**: 0.3.0
14
+
15
+ ## Architecture
16
+
17
+ ```
18
+ Legion::Extensions::Conditioner
19
+ ├── Actors/
20
+ │ └── Conditioner # Subscription actor consuming condition evaluation requests
21
+ ├── Runners/
22
+ │ └── Conditioner # Executes conditional logic against task payloads
23
+ │ ├── check # Main entry point: evaluates conditions, dispatches or fails
24
+ │ └── send_task # Routes to transformation or task queue based on result
25
+ ├── Helpers/
26
+ │ ├── Condition # Condition parsing (all/any nesting, dotted-path facts)
27
+ │ └── Comparator # Comparison operator implementations (class methods)
28
+ └── Transport/
29
+ ├── Exchanges/Task # Publishes to the task exchange
30
+ ├── Queues/Conditioner # Subscribes to condition evaluation queue
31
+ └── Messages/Conditioner # Message format for condition requests
32
+ ```
33
+
34
+ ## Key Files
35
+
36
+ | Path | Purpose |
37
+ |------|---------|
38
+ | `lib/legion/extensions/conditioner.rb` | Entry point, extension registration |
39
+ | `lib/legion/extensions/conditioner/runners/conditioner.rb` | Core condition evaluation logic |
40
+ | `lib/legion/extensions/conditioner/helpers/condition.rb` | Condition parsing and all/any evaluation |
41
+ | `lib/legion/extensions/conditioner/helpers/comparator.rb` | Comparison operator implementations |
42
+ | `lib/legion/extensions/conditioner/actors/conditioner.rb` | AMQP subscription actor |
43
+
44
+ ## Condition Rule Format
45
+
46
+ Rules use `all`/`any` grouping with `fact`/`operator`/`value` entries. Facts use dot notation to address nested payload keys. Groups can be nested arbitrarily.
47
+
48
+ ```json
49
+ {
50
+ "all": [
51
+ { "fact": "response.code", "operator": "greater_or_equal", "value": 200 },
52
+ { "any": [
53
+ { "fact": "action", "operator": "equal", "value": "opened" },
54
+ { "fact": "action", "operator": "equal", "value": "reopened" }
55
+ ]}
56
+ ]
57
+ }
58
+ ```
59
+
60
+ ## Operators
61
+
62
+ ### Binary (require `fact` + `value`)
63
+
64
+ | Operator | Description |
65
+ |----------|-------------|
66
+ | `equal` | Exact equality |
67
+ | `not_equal` | Inequality |
68
+ | `greater_than` | Numeric greater than |
69
+ | `less_than` | Numeric less than |
70
+ | `greater_or_equal` | Numeric greater than or equal |
71
+ | `less_or_equal` | Numeric less than or equal |
72
+ | `between` | Value within range (`value` is `[min, max]`) |
73
+ | `contains` | String contains substring |
74
+ | `starts_with` | String starts with prefix |
75
+ | `ends_with` | String ends with suffix |
76
+ | `matches` | String matches regex pattern |
77
+ | `in_set` | Value is in the given array |
78
+ | `not_in_set` | Value is not in the given array |
79
+ | `size_equal` | Collection or string size equals value |
80
+
81
+ ### Unary (require `fact` only)
82
+
83
+ | Operator | Description |
84
+ |----------|-------------|
85
+ | `nil` | Value is nil |
86
+ | `not_nil` | Value is not nil |
87
+ | `is_true` | Value is truthy |
88
+ | `is_false` | Value is falsy |
89
+ | `is_string` | Value is a String |
90
+ | `is_array` | Value is an Array |
91
+ | `is_integer` | Value is an Integer |
92
+ | `empty` | Value is nil or empty |
93
+ | `not_empty` | Value is present and not empty |
94
+
95
+ ## Condition Evaluation Logic
96
+
97
+ After evaluation, the runner routes based on outcome:
98
+ - Condition passes + transformation present: `transformation.queued` (routes to `task.subtask.transform`)
99
+ - Condition passes + routing key present: `task.queued` (routes to `runner_routing_key`)
100
+ - Condition passes but no routing info: `task.exception` (`send_task` raises `MissingArgument`)
101
+ - Condition fails: `conditioner.failed` (`send_task` is skipped)
102
+
103
+ Each evaluation also returns an explanation chain with per-rule results including actual values, for use by lex-synapse and standalone callers.
104
+
105
+ ## Standalone Client
106
+
107
+ `Legion::Extensions::Conditioner::Client` includes the `Conditioner` runner. Instantiate without the full framework:
108
+
109
+ ```ruby
110
+ require 'legion/extensions/conditioner/client'
111
+ client = Legion::Extensions::Conditioner::Client.new
112
+ result = client.evaluate(conditions: { all: [...] }, values: { ... })
113
+ result[:valid] # => true/false
114
+ result[:explanation] # => per-rule results with actual values
115
+ ```
116
+
117
+ ## Dependencies
118
+
119
+ | Gem | Purpose |
120
+ |-----|---------|
121
+ | `legion-exceptions` | Exception handling |
122
+
123
+ ## Testing
124
+
125
+ ```bash
126
+ bundle install
127
+ bundle exec rspec # 140 examples, 0 failures
128
+ bundle exec rubocop # 0 offenses
129
+ ```
130
+
131
+ Spec files: `spec/legion/extensions/conditioner_spec.rb`, `spec/legion/extensions/comparator_spec.rb`, `spec/legion/extensions/condition_spec.rb`, `spec/legion/extensions/conditioner/runners/conditioner_spec.rb`
132
+
133
+ ---
134
+
135
+ **Maintained By**: Matthew Iverson (@Esity)
data/Dockerfile CHANGED
@@ -5,4 +5,4 @@ RUN apk update && apk add build-base tzdata postgresql-dev mysql-client mariadb-
5
5
 
6
6
  COPY . ./
7
7
  RUN gem install lex-conditioner legion-data --no-document --no-prerelease
8
- CMD ruby $(which legionio)
8
+ CMD ruby --yjit $(which legionio)
data/Gemfile CHANGED
@@ -1,3 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
6
+
7
+ group :test do
8
+ gem 'rake'
9
+ gem 'rspec', '~> 3.13'
10
+ gem 'rspec_junit_formatter'
11
+ gem 'rubocop', '~> 1.75'
12
+ gem 'rubocop-rspec'
13
+ gem 'simplecov'
14
+ end
data/README.md CHANGED
@@ -1,38 +1,125 @@
1
- # Legion::Extensions::Conditioner
1
+ # lex-conditioner
2
2
 
3
- A core Legion Extension used to evaluate conditions for sub tasks to run
3
+ Conditional rule engine for [LegionIO](https://github.com/LegionIO/LegionIO). Evaluates JSON-based rules against task payloads to determine whether downstream tasks should execute, enabling branching logic in task chains.
4
4
 
5
5
  ## Installation
6
6
 
7
- Add this line to your application's Gemfile:
7
+ ```bash
8
+ gem install lex-conditioner
9
+ ```
10
+
11
+ Or add to your Gemfile:
8
12
 
9
13
  ```ruby
10
14
  gem 'lex-conditioner'
11
15
  ```
12
16
 
13
- And then execute:
17
+ ## Standalone Client
18
+
19
+ Use the conditioner without the full LegionIO framework:
20
+
21
+ ```ruby
22
+ require 'legion/extensions/conditioner/client'
23
+
24
+ client = Legion::Extensions::Conditioner::Client.new
25
+
26
+ result = client.evaluate(
27
+ conditions: { all: [
28
+ { fact: 'response.code', operator: 'greater_or_equal', value: 200 },
29
+ { fact: 'response.code', operator: 'less_than', value: 300 }
30
+ ] },
31
+ values: { response: { code: 200, body: 'OK' } }
32
+ )
33
+
34
+ result[:valid] # => true
35
+ result[:explanation] # => { valid: true, group: :all, rules: [...] }
36
+ ```
37
+
38
+ The explanation includes per-rule results with actual values:
14
39
 
15
- $ bundle install
40
+ ```ruby
41
+ result[:explanation][:rules]
42
+ # => [
43
+ # { fact: "response.code", operator: "greater_or_equal", value: 200, actual: 200, result: true },
44
+ # { fact: "response.code", operator: "less_than", value: 300, actual: 200, result: true }
45
+ # ]
46
+ ```
16
47
 
17
- Or install it yourself as:
48
+ ## Condition Format
18
49
 
19
- $ gem install lex-conditioner
50
+ Rules use `all`/`any` grouping with `fact`/`operator`/`value` entries. Facts use dot notation for nested keys.
20
51
 
21
- ## Adding to Legion
22
- You can manually install with a `gem install lex-http` command or by adding it into your settings with something like this
23
52
  ```json
24
53
  {
25
- "extensions": {
26
- "conditioner": {
27
- "enabled": true, "workers": 1
28
- }
29
- }
54
+ "all": [
55
+ { "fact": "response.code", "operator": "greater_or_equal", "value": 200 },
56
+ { "any": [
57
+ { "fact": "action", "operator": "equal", "value": "opened" },
58
+ { "fact": "action", "operator": "equal", "value": "reopened" }
59
+ ]}
60
+ ]
30
61
  }
31
62
  ```
32
63
 
33
- ## Usage
64
+ ## Operators
65
+
66
+ ### Binary (require `fact` + `value`)
67
+
68
+ | Operator | Description |
69
+ |----------|-------------|
70
+ | `equal` | Exact equality |
71
+ | `not_equal` | Inequality |
72
+ | `greater_than` | Numeric greater than |
73
+ | `less_than` | Numeric less than |
74
+ | `greater_or_equal` | Numeric greater than or equal |
75
+ | `less_or_equal` | Numeric less than or equal |
76
+ | `between` | Value within range (value is `[min, max]`) |
77
+ | `contains` | String contains substring |
78
+ | `starts_with` | String starts with prefix |
79
+ | `ends_with` | String ends with suffix |
80
+ | `matches` | String matches regex pattern |
81
+ | `in_set` | Value is in the given array |
82
+ | `not_in_set` | Value is not in the given array |
83
+ | `size_equal` | Collection/string size equals value |
84
+
85
+ ### Unary (require `fact` only)
86
+
87
+ | Operator | Description |
88
+ |----------|-------------|
89
+ | `nil` | Value is nil |
90
+ | `not_nil` | Value is not nil |
91
+ | `is_true` | Value is truthy |
92
+ | `is_false` | Value is falsy |
93
+ | `is_string` | Value is a String |
94
+ | `is_array` | Value is an Array |
95
+ | `is_integer` | Value is an Integer |
96
+ | `empty` | Value is nil or empty |
97
+ | `not_empty` | Value is present and not empty |
98
+
99
+ ## Runners
100
+
101
+ ### Conditioner
102
+
103
+ #### `check(conditions:, **payload)`
104
+
105
+ Evaluates conditions against the payload. Routes to transformation or task queue based on result:
106
+
107
+ - Condition passes + transformation present: routes to `task.subtask.transform`
108
+ - Condition passes + routing key present: routes to `runner_routing_key`
109
+ - Condition fails: `conditioner.failed`, no dispatch
110
+
111
+ ## Transport
112
+
113
+ - **Exchange**: `task` (inherits from `Legion::Transport::Exchanges::Task`)
114
+ - **Queue**: `task.conditioner`
115
+ - **Routing keys**: `task.subtask`, `task.subtask.conditioner`
116
+
117
+ ## Requirements
34
118
 
119
+ - Ruby >= 3.4
120
+ - [LegionIO](https://github.com/LegionIO/LegionIO) framework (for AMQP actor mode)
121
+ - Standalone Client works without the framework
35
122
 
36
123
  ## License
37
124
 
38
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
125
+ MIT
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
 
data/docker_deploy.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  name = 'conditioner'
4
5
  require "./lib/legion/extensions/#{name}/version"
@@ -1,6 +1,6 @@
1
- lib = File.expand_path('lib', __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'legion/extensions/conditioner/version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/legion/extensions/conditioner/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'lex-conditioner'
@@ -8,28 +8,29 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Esity']
9
9
  spec.email = ['matthewdiverson@gmail.com']
10
10
 
11
- spec.summary = 'LEX-Conditioner is used to apply conditional statements to tasks'
12
- spec.description = 'Runs relationship conditional statements against tasks in a relationship'
13
- spec.homepage = 'https://bitbucket.org/legion-io/lex-conditioner'
11
+ spec.summary = 'Conditional rule engine for LegionIO task chains'
12
+ spec.description = 'Evaluates JSON-based rules against task payloads with 18+ operators, structured explanations, and standalone client support'
13
+ spec.homepage = 'https://github.com/LegionIO/lex-conditioner'
14
14
  spec.license = 'MIT'
15
- spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
15
+ spec.required_ruby_version = '>= 3.4'
16
16
 
17
17
  spec.metadata['homepage_uri'] = spec.homepage
18
- spec.metadata['source_code_uri'] = 'https://bitbucket.org/legion-io/lex-conditioner'
19
- spec.metadata['documentation_uri'] = 'https://legionio.atlassian.net/wiki/spaces/LEX/pages/614957181'
20
- spec.metadata['changelog_uri'] = 'https://legionio.atlassian.net/wiki/spaces/LEX/pages/612270436'
21
- spec.metadata['bug_tracker_uri'] = 'https://bitbucket.org/legion-io/lex-conditioner/issues'
18
+ spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-conditioner'
19
+ spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-conditioner'
20
+ spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-conditioner/blob/main/CHANGELOG.md'
21
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-conditioner/issues'
22
+ spec.metadata['rubygems_mfa_required'] = 'true'
22
23
 
23
24
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
25
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
26
  end
26
27
  spec.require_paths = ['lib']
27
28
 
28
- spec.add_development_dependency 'legionio'
29
- spec.add_development_dependency 'rake'
30
- spec.add_development_dependency 'rspec'
31
- spec.add_development_dependency 'rubocop'
32
- spec.add_development_dependency 'simplecov'
33
-
34
- spec.add_dependency 'legion-exceptions'
29
+ spec.add_dependency 'legion-cache', '>= 1.3.11'
30
+ spec.add_dependency 'legion-crypt', '>= 1.4.9'
31
+ spec.add_dependency 'legion-data', '>= 1.4.17'
32
+ spec.add_dependency 'legion-json', '>= 1.2.1'
33
+ spec.add_dependency 'legion-logging', '>= 1.3.2'
34
+ spec.add_dependency 'legion-settings', '>= 1.3.14'
35
+ spec.add_dependency 'legion-transport', '>= 1.3.9'
35
36
  end
@@ -1,16 +1,22 @@
1
- module Legion::Extensions::Conditioner
2
- module Actor
3
- class Conditioner < Legion::Extensions::Actors::Subscription
4
- def runner_function
5
- 'check'
6
- end
1
+ # frozen_string_literal: true
7
2
 
8
- def check_subtask?
9
- false
10
- end
3
+ module Legion
4
+ module Extensions
5
+ module Conditioner
6
+ module Actor
7
+ class Conditioner < Legion::Extensions::Actors::Subscription
8
+ def runner_function
9
+ 'check'
10
+ end
11
+
12
+ def check_subtask?
13
+ false
14
+ end
11
15
 
12
- def generate_task?
13
- false
16
+ def generate_task?
17
+ false
18
+ end
19
+ end
14
20
  end
15
21
  end
16
22
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helpers/condition'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Conditioner
8
+ class Client
9
+ def evaluate(conditions:, values:)
10
+ conditions_json = conditions.is_a?(String) ? conditions : Legion::JSON.dump(conditions)
11
+ condition = Condition.new(conditions: conditions_json, values: values)
12
+ {
13
+ valid: condition.valid?,
14
+ explanation: condition.explain
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Legion
2
4
  module Extensions
3
5
  module Conditioner
@@ -18,25 +20,84 @@ module Legion
18
20
  !values[fact].nil?
19
21
  end
20
22
 
21
- def self.is_false?(fact, values) # rubocop:disable Naming/PredicateName
22
- true unless values[fact]
23
+ def self.false?(fact, values)
24
+ values[fact] ? false : true
23
25
  end
24
26
 
25
- def self.is_true?(fact, values) # rubocop:disable Naming/PredicateName
27
+ def self.true?(fact, values)
26
28
  values[fact]
27
29
  end
28
30
 
29
- def self.is_array?(fact, values) # rubocop:disable Naming/PredicateName
30
- !values[fact]
31
+ def self.array?(fact, values)
32
+ values[fact].is_a? Array
31
33
  end
32
34
 
33
- def self.is_string?(fact, values) # rubocop:disable Naming/PredicateName
35
+ def self.string?(fact, values)
34
36
  values[fact].is_a? String
35
37
  end
36
38
 
37
- def self.is_integer?(fact, values) # rubocop:disable Naming/PredicateName
39
+ def self.integer?(fact, values)
38
40
  values[fact].is_a? Integer
39
41
  end
42
+
43
+ def self.greater_than?(fact, value, values)
44
+ values[fact] > value
45
+ end
46
+
47
+ def self.less_than?(fact, value, values)
48
+ values[fact] < value
49
+ end
50
+
51
+ def self.greater_or_equal?(fact, value, values)
52
+ values[fact] >= value
53
+ end
54
+
55
+ def self.less_or_equal?(fact, value, values)
56
+ values[fact] <= value
57
+ end
58
+
59
+ def self.between?(fact, value, values)
60
+ values[fact].between?(value[0], value[1])
61
+ end
62
+
63
+ def self.contains?(fact, value, values)
64
+ values[fact].to_s.include?(value.to_s)
65
+ end
66
+
67
+ def self.starts_with?(fact, value, values)
68
+ values[fact].to_s.start_with?(value.to_s)
69
+ end
70
+
71
+ def self.ends_with?(fact, value, values)
72
+ values[fact].to_s.end_with?(value.to_s)
73
+ end
74
+
75
+ def self.matches?(fact, value, values)
76
+ Regexp.new(value).match?(values[fact].to_s)
77
+ end
78
+
79
+ def self.in_set?(fact, value, values)
80
+ Array(value).include?(values[fact])
81
+ end
82
+
83
+ def self.not_in_set?(fact, value, values)
84
+ !Array(value).include?(values[fact])
85
+ end
86
+
87
+ def self.empty?(fact, values)
88
+ val = values[fact]
89
+ val.nil? || (val.respond_to?(:empty?) && val.empty?)
90
+ end
91
+
92
+ def self.not_empty?(fact, values)
93
+ val = values[fact]
94
+ !val.nil? && !(val.respond_to?(:empty?) && val.empty?)
95
+ end
96
+
97
+ def self.size_equal?(fact, value, values)
98
+ val = values[fact]
99
+ val.respond_to?(:size) && val.size == value
100
+ end
40
101
  end
41
102
  end
42
103
  end