Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
schlick committed Dec 13, 2022
2 parents 93ed320 + 21d11a3 commit 677d839
Show file tree
Hide file tree
Showing 18 changed files with 709 additions and 181 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/coverage
Gemfile.lock
coverage
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Changelog
All notable changes to this gem will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [1.6.0] - 2022-12-13
### Added
- Multiple outcomes: the ability to continue walking a tree, returning all outcomes instead of stopping at the first outcome
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
source "https://rubygems.org"
gem 'boolean_dsl', github: 'jobready/boolean_dsl', branch: 'develop'
gemspec

gem 'boolean_dsl', github: 'jobready/boolean_dsl', branch: 'develop'
gem 'simplecov', group: :test, require: nil
91 changes: 0 additions & 91 deletions Gemfile.lock

This file was deleted.

41 changes: 30 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,39 @@ Or install it yourself as:

## Usage

Require everything
Single outcome:

```ruby
require 'rules_engine'
@name = options.fetch(:name)
@reference = options.fetch(:reference)
@parameter = options.fetch(:parameter)

true_outcome = RulesEngine::Outcome.new(reference:'some category', name:'true outcome',parameter:'some parameter')
false_outcome = RulesEngine::Outcome.new(reference:'some category', 'name:false outcome', parameter:'another parameter')
root_rule = RulesEngine::Condition.new(name:'condition name', condition:'2 > 1', when_true:true_outcome, when_false:false_outcome)
set = RulesEngine::Set.new(root:root_rule, name:'rule set name')
walker = RulesEngine::Walker.new(set:set, object:some_object)
true_outcome = RulesEngine::Outcome.new(name: "Outcome 1", values: "Outcome 1 Values")
false_outcome = RulesEngine::Outcome.new(name: "Outcome 2", values: "Outcome 2 Values")
root = RulesEngine::Condition.new(name: "Root", condition: "2 > 1", when_true: true_outcome, when_false: false_outcome)
set = RulesEngine::Set.new(name: "Single Outcome", root: root)
walker = RulesEngine::Walker.new(set: set, event_logger: nil)
walker.walk

# Executing Rule Set Single Outcome
# Evaluated condition 2 > 1, result is true (overridden: false)
# => #<RulesEngine::Outcome:... @name="Outcome 1", @values="Outcome 1 Values">
```

Multiple outcomes:

```ruby
outcome_1 = RulesEngine::Outcome.new(name: "Outcome 1", values: "Outcome 1 Values")
outcome_2 = RulesEngine::Outcome.new(name: "Outcome 2", values: "Outcome 2 Values")
outcome_3 = RulesEngine::Outcome.new(name: "Outcome 3", values: "Outcome 3 Values")
outcome_4 = RulesEngine::Outcome.new(name: "Outcome 4", values: "Outcome 4 Values")
condition_1 = RulesEngine::Condition.new(name: "Condition 1", condition: "2 < 1", when_true_outcome: outcome_3, when_false_outcome: outcome_4)
root = RulesEngine::Condition.new(name: "Root", condition: "2 > 1", when_true_outcome: outcome_1, when_true_condition: condition_1, when_false_outcome: outcome_2, when_false_condition: condition_1)
set = RulesEngine::Set.new(name: "Multiple Outcomes", root: root, multiple_outcomes: true)
walker = RulesEngine::Walker.new(set: set, event_logger: nil)
walker.walk

# Executing Rule Set Multiple Outcomes
# Evaluated condition 2 > 1, result is true (overridden: false)
# Evaluated condition 2 < 1, result is false (overridden: false)
# => [#<RulesEngine::Outcome:... @name="Outcome 1", @values="Outcome 1 Values">,
#<RulesEngine::Outcome:... @name="Outcome 4", @values="Outcome 4 Values">]
```

## Contributing
Expand Down
24 changes: 23 additions & 1 deletion lib/rules_engine/condition.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
class RulesEngine::Condition
attr_accessor :name, :condition, :when_true, :when_false, :original, :override
attr_accessor :name,
:condition,
:when_true,
:when_false,
:original,
:override,
:when_true_outcome,
:when_false_outcome,
:when_true_condition,
:when_false_condition

def initialize(options = {})
@name = options.fetch(:name)
Expand All @@ -8,6 +17,10 @@ def initialize(options = {})
@when_false = options.fetch(:when_false, nil)
@original = options.fetch(:original, nil)
@override = options.fetch(:override, nil)
@when_true_outcome = options.fetch(:when_true_outcome, nil)
@when_false_outcome = options.fetch(:when_false_outcome, nil)
@when_true_condition = options.fetch(:when_true_condition, nil)
@when_false_condition = options.fetch(:when_false_condition, nil)
end

def override?
Expand All @@ -25,5 +38,14 @@ def execute(context)
def outcome(which)
which ? when_true : when_false
end

# For sets with multiple outcomes
def outcomes(which)
if which
[when_true_outcome, when_true_condition]
else
[when_false_outcome, when_false_condition]
end
end
end

6 changes: 5 additions & 1 deletion lib/rules_engine/outcome.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
class RulesEngine::Outcome
attr_accessor :name, :values, :reference
attr_accessor :name,
:values,
:reference,
:original

def initialize(options = {})
@name = options.fetch(:name)
@values = options.fetch(:values)
@reference = options.fetch(:reference, nil)
@original = options.fetch(:original, nil)
end
end
11 changes: 10 additions & 1 deletion lib/rules_engine/set.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
class RulesEngine::Set
attr_reader :root, :name
attr_reader :name,
:root,
:original,
:multiple_outcomes

def initialize(options = {})
@root = options.fetch(:root)
@name = options.fetch(:name)
@original = options.fetch(:original, nil)
@multiple_outcomes = options.fetch(:multiple_outcomes, false)
end

def multiple_outcomes?
multiple_outcomes
end
end
2 changes: 1 addition & 1 deletion lib/rules_engine/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module RulesEngine
VERSION = '1.3.0'
VERSION = '1.6.0'
end
25 changes: 21 additions & 4 deletions lib/rules_engine/walker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,33 @@ def walk_set(set)
logger.info("Executing Rule Set #{set.name}")

node = set.root
outcome = nil
condition = nil
outcomes = []

loop do
unless node.is_a?(RulesEngine::Condition)
add_event(set, node, nil) if node
return node
if set.multiple_outcomes?
if outcome
add_event(set, outcome, nil)
outcomes << outcome
end
return outcomes unless node
else
unless node.is_a?(RulesEngine::Condition)
add_event(set, node, nil) if node
return node
end
end

which = node.execute(context)
logger.info("Evaluated condition #{node.condition}, result is #{which} (overridden: #{node.override?})")
add_event(set, node, which)
node = node.outcome(which)

if set.multiple_outcomes?
outcome, node = node.outcomes(which)
else
node = node.outcome(which)
end
end
end

Expand Down
4 changes: 1 addition & 3 deletions rules_engine.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ Gem::Specification.new do |s|

s.add_development_dependency 'bundler', '~> 1.0'
s.add_development_dependency 'rspec', '~> 2.14'
s.add_development_dependency 'factory_girl', '~> 4.4'
s.add_development_dependency 'factory_bot', '~> 4.4'
s.add_development_dependency 'cane', '~> 2.6'
s.add_development_dependency 'byebug', '~> 2.7'
s.add_development_dependency 'rake', '~> 10.1'
s.add_development_dependency 'coveralls'
s.add_development_dependency 'codeclimate-test-reporter'
s.add_dependency 'activesupport'
s.add_dependency 'boolean_dsl'

Expand Down
2 changes: 1 addition & 1 deletion scripts/buildbox.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e

echo '--- setting ruby version'
rbenv local 2.1.2
rbenv local 2.3.6

echo '--- bundling'
bundle install -j $(nproc) --without production --quiet
Expand Down
2 changes: 1 addition & 1 deletion spec/factories.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
FactoryGirl.define do
FactoryBot.define do
end
Loading

0 comments on commit 677d839

Please sign in to comment.