rulezilla 0.1.4 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yaml +36 -0
- data/.github/workflows/codeql-analysis.yaml +70 -0
- data/.github/workflows/dobby-actions.yml +29 -0
- data/.github/workflows/gem-publish.yaml +46 -0
- data/.github/workflows/version-forget-me-not.yaml +19 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +61 -0
- data/.ruby-version +1 -0
- data/CODEOWNERS +3 -0
- data/Gemfile +2 -4
- data/LICENSE.txt +9 -0
- data/README.md +34 -28
- data/catalog-info.yaml +8 -0
- data/lib/rulezilla/basic_support.rb +3 -3
- data/lib/rulezilla/dsl.rb +27 -14
- data/lib/rulezilla/node.rb +10 -11
- data/lib/rulezilla/tree.rb +23 -14
- data/lib/rulezilla/version.rb +3 -1
- data/lib/rulezilla.rb +2 -31
- data/rulezilla.gemspec +15 -8
- data/spec/features/{rulezilla_dsl_framwork.feature → rulezilla_dsl_framework.feature} +50 -3
- data/spec/features/step_definitions/rulezilla_dsl_framework_steps.rb +36 -54
- data/spec/spec_helper.rb +33 -13
- metadata +74 -17
- data/Gemfile.lock +0 -44
- data/lib/rulezilla/rule_builder/gherkin_to_condition_rule.rb +0 -63
- data/lib/rulezilla/rule_builder/gherkin_to_result_rule.rb +0 -49
- data/lib/rulezilla/rule_builder.rb +0 -101
- data/spec/features/gherkin_dsl_framework.feature +0 -90
- data/spec/features/gherkin_rules/animal_rule.feature +0 -16
- data/spec/features/gherkin_rules/duration_rule.feature +0 -14
- data/spec/features/step_definitions/rule_steps.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 43dfbbf1981a5b2dfa4fc2f479115160b280ef929216fffbe1bb724a580e300d
|
4
|
+
data.tar.gz: fe5f3f26f62751725db9e629447e90032b3a946d0894389df8b0d2b445dc7934
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4fa1e6b4b54040a5323a01662e88d32f981a1278dcc1475c07b3743ed56839445c44cd57efa629ca5398bf6bf2e4f1add1605b36d8f728de3d91c02400d286f
|
7
|
+
data.tar.gz: b1c7b5222c8c0329d45da874cf5c076087751019e573853be2d69c89ace8c763e73ad9d18e5ae1354619b9d3adacd5a5378f2febb6c8fa02fc092df65f944725
|
@@ -0,0 +1,36 @@
|
|
1
|
+
name: Ruby CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
|
6
|
+
env:
|
7
|
+
CI: true
|
8
|
+
permissions:
|
9
|
+
contents: read
|
10
|
+
statuses: write
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
build:
|
14
|
+
runs-on: ubuntu-latest
|
15
|
+
defaults:
|
16
|
+
run:
|
17
|
+
working-directory: ./
|
18
|
+
|
19
|
+
strategy:
|
20
|
+
matrix:
|
21
|
+
ruby-version: [2.7, 3.0, 3.1]
|
22
|
+
|
23
|
+
steps:
|
24
|
+
- uses: actions/checkout@v3
|
25
|
+
- name: Set up Ruby
|
26
|
+
uses: ruby/setup-ruby@v1
|
27
|
+
with:
|
28
|
+
ruby-version: ${{ matrix.ruby-version }}
|
29
|
+
|
30
|
+
- name: Install dependencies
|
31
|
+
run: bundle install
|
32
|
+
- name: Rubocop Check
|
33
|
+
run: bundle exec rubocop
|
34
|
+
- name: Run all tests
|
35
|
+
run: bundle exec rspec
|
36
|
+
shell: bash
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
2
|
+
# to commit it to your repository.
|
3
|
+
#
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
5
|
+
# or to provide custom queries or build logic.
|
6
|
+
#
|
7
|
+
# ******** NOTE ********
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
10
|
+
# supported CodeQL languages.
|
11
|
+
#
|
12
|
+
name: "CodeQL"
|
13
|
+
|
14
|
+
on:
|
15
|
+
push:
|
16
|
+
branches: [ master ]
|
17
|
+
pull_request:
|
18
|
+
# The branches below must be a subset of the branches above
|
19
|
+
branches: [ master ]
|
20
|
+
schedule:
|
21
|
+
- cron: '42 8 * * 0'
|
22
|
+
|
23
|
+
jobs:
|
24
|
+
analyze:
|
25
|
+
name: Analyze
|
26
|
+
runs-on: ubuntu-latest
|
27
|
+
permissions:
|
28
|
+
actions: read
|
29
|
+
contents: read
|
30
|
+
security-events: write
|
31
|
+
|
32
|
+
strategy:
|
33
|
+
fail-fast: false
|
34
|
+
matrix:
|
35
|
+
language: [ 'ruby' ]
|
36
|
+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
37
|
+
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
38
|
+
|
39
|
+
steps:
|
40
|
+
- name: Checkout repository
|
41
|
+
uses: actions/checkout@v2
|
42
|
+
|
43
|
+
# Initializes the CodeQL tools for scanning.
|
44
|
+
- name: Initialize CodeQL
|
45
|
+
uses: github/codeql-action/init@v1
|
46
|
+
with:
|
47
|
+
languages: ${{ matrix.language }}
|
48
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
49
|
+
# By default, queries listed here will override any specified in a config file.
|
50
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
51
|
+
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
52
|
+
|
53
|
+
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
54
|
+
# If this step fails, then you should remove it and run the build manually (see below)
|
55
|
+
- name: Autobuild
|
56
|
+
uses: github/codeql-action/autobuild@v1
|
57
|
+
|
58
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
59
|
+
# 📚 https://git.io/JvXDl
|
60
|
+
|
61
|
+
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
62
|
+
# and modify them (or add more) to build your code if your project
|
63
|
+
# uses a compiled language
|
64
|
+
|
65
|
+
#- run: |
|
66
|
+
# make bootstrap
|
67
|
+
# make release
|
68
|
+
|
69
|
+
- name: Perform CodeQL Analysis
|
70
|
+
uses: github/codeql-action/analyze@v1
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
name: "Dobby action"
|
3
|
+
on:
|
4
|
+
issue_comment:
|
5
|
+
types: [created]
|
6
|
+
permissions:
|
7
|
+
contents: read
|
8
|
+
jobs:
|
9
|
+
pr_commented:
|
10
|
+
runs-on: ubuntu-20.04
|
11
|
+
if: startsWith(github.event.comment.body, '/dobby')
|
12
|
+
env:
|
13
|
+
BUNDLE_WITHOUT: "development:test"
|
14
|
+
steps:
|
15
|
+
- name: Checkout action
|
16
|
+
uses: actions/checkout@v2
|
17
|
+
with:
|
18
|
+
repository: 'simplybusiness/dobby'
|
19
|
+
ref: 'v3.0.0'
|
20
|
+
- name: Set up ruby
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
bundler-cache: true
|
24
|
+
- name: Bump version
|
25
|
+
uses: simplybusiness/dobby@v3.0.0
|
26
|
+
env:
|
27
|
+
DOBBY_APP_ID: ${{ secrets.DOBBY_APP_ID }}
|
28
|
+
DOBBY_PRIVATE_KEY: ${{ secrets.DOBBY_PRIVATE_KEY }}
|
29
|
+
VERSION_FILE_PATH: lib/rulezilla/version.rb
|
@@ -0,0 +1,46 @@
|
|
1
|
+
name: Publish Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
|
7
|
+
permissions:
|
8
|
+
contents: write
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
build:
|
12
|
+
name: Build and Publish
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v3
|
16
|
+
- name: Set up Ruby
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
bundler-cache: true
|
20
|
+
- name: Publish to RubyGems
|
21
|
+
run: |
|
22
|
+
mkdir -p $HOME/.gem
|
23
|
+
touch $HOME/.gem/credentials
|
24
|
+
chmod 0600 $HOME/.gem/credentials
|
25
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
26
|
+
gem build *.gemspec
|
27
|
+
gem push *.gem
|
28
|
+
env:
|
29
|
+
GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
|
30
|
+
- name: Get Gem Version
|
31
|
+
id: get-gem-version
|
32
|
+
run: echo "::set-output name=GEM_VERSION::$(bundle exec ruby -e 'puts Rulezilla::VERSION')"
|
33
|
+
- name: Create Release
|
34
|
+
uses: actions/github-script@v6
|
35
|
+
env:
|
36
|
+
GEM_VERSION: ${{ steps.get-gem-version.outputs.GEM_VERSION }}
|
37
|
+
with:
|
38
|
+
result-encoding: string
|
39
|
+
script: |
|
40
|
+
const { GEM_VERSION } = process.env
|
41
|
+
github.rest.repos.createRelease({
|
42
|
+
owner: context.repo.owner,
|
43
|
+
repo: context.repo.repo,
|
44
|
+
tag_name: GEM_VERSION,
|
45
|
+
generate_release_notes: true,
|
46
|
+
})
|
@@ -0,0 +1,19 @@
|
|
1
|
+
name: Check version
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
types: [opened, synchronize]
|
8
|
+
permissions:
|
9
|
+
contents: read
|
10
|
+
statuses: write
|
11
|
+
jobs:
|
12
|
+
version-check:
|
13
|
+
runs-on: ubuntu-18.04
|
14
|
+
|
15
|
+
steps:
|
16
|
+
- uses: simplybusiness/version-forget-me-not@v2.3.0
|
17
|
+
env:
|
18
|
+
ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
19
|
+
VERSION_FILE_PATH: "lib/rulezilla/version.rb"
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2022-07-06 10:13:12 UTC using RuboCop version 1.31.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: Include.
|
11
|
+
# Include: **/*.gemspec
|
12
|
+
Gemspec/RequiredRubyVersion:
|
13
|
+
Exclude:
|
14
|
+
- 'rulezilla.gemspec'
|
15
|
+
|
16
|
+
# Offense count: 1
|
17
|
+
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
|
18
|
+
Metrics/AbcSize:
|
19
|
+
Max: 20
|
20
|
+
|
21
|
+
# Offense count: 2
|
22
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
23
|
+
# IgnoredMethods: refine
|
24
|
+
Metrics/BlockLength:
|
25
|
+
Max: 32
|
26
|
+
|
27
|
+
# Offense count: 2
|
28
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
29
|
+
Metrics/MethodLength:
|
30
|
+
Max: 19
|
31
|
+
|
32
|
+
# Offense count: 3
|
33
|
+
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
|
34
|
+
# NamePrefix: is_, has_, have_
|
35
|
+
# ForbiddenPrefixes: is_, has_, have_
|
36
|
+
# AllowedMethods: is_a?
|
37
|
+
# MethodDefinitionMacros: define_method, define_singleton_method
|
38
|
+
Naming/PredicateName:
|
39
|
+
Exclude:
|
40
|
+
- 'spec/**/*'
|
41
|
+
- 'lib/rulezilla/node.rb'
|
42
|
+
- 'lib/rulezilla/tree.rb'
|
43
|
+
|
44
|
+
# Offense count: 6
|
45
|
+
# Configuration parameters: AllowedConstants.
|
46
|
+
Style/Documentation:
|
47
|
+
Exclude:
|
48
|
+
- 'spec/**/*'
|
49
|
+
- 'test/**/*'
|
50
|
+
- 'lib/rulezilla/basic_support.rb'
|
51
|
+
- 'lib/rulezilla/dsl.rb'
|
52
|
+
- 'lib/rulezilla/node.rb'
|
53
|
+
- 'lib/rulezilla/tree.rb'
|
54
|
+
- 'lib/rulezilla/version.rb'
|
55
|
+
|
56
|
+
# Offense count: 3
|
57
|
+
# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
|
58
|
+
Style/GuardClause:
|
59
|
+
Exclude:
|
60
|
+
- 'lib/rulezilla/dsl.rb'
|
61
|
+
- 'rulezilla.gemspec'
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.1.2
|
data/CODEOWNERS
ADDED
data/Gemfile
CHANGED
data/LICENSE.txt
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Copyright (c) 2013-2016 Simply Business
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,43 +1,43 @@
|
|
1
|
-
[![
|
1
|
+
[![Build Status](https://semaphoreci.com/api/v1/projects/e488365d-9c57-4431-916a-72aea091d1b5/229083/shields_badge.svg)](https://semaphoreci.com/simplybusiness/rulezilla)
|
2
2
|
[![Code Climate](https://codeclimate.com/repos/53ecc0416956800c1d01f6bf/badges/76b47eaeffc33e312508/gpa.svg)](https://codeclimate.com/repos/53ecc0416956800c1d01f6bf/feed)
|
3
|
-
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rulezilla.svg)](http://badge.fury.io/rb/rulezilla)
|
4
4
|
|
5
5
|
rulezilla
|
6
6
|
=========
|
7
7
|
|
8
|
-
This
|
8
|
+
This provides a DSL to implement rules for various tasks. In the current version we are still relying on user to have a certain level of Ruby knowledge
|
9
|
+
in order to be able to use this DSL. The ultimate goal is for people without prior Ruby knowledge to be able to change and even write the Rule.
|
9
10
|
|
10
11
|
|
11
12
|
# Installation
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
## Implementation
|
14
|
+
## Using `Gemfile`
|
16
15
|
|
17
|
-
|
16
|
+
Add the following line to your `Gemfile`:
|
18
17
|
|
19
|
-
|
18
|
+
gem 'rulezilla'
|
20
19
|
|
21
|
-
|
20
|
+
Then run:
|
22
21
|
|
23
|
-
|
22
|
+
bundle install
|
24
23
|
|
25
|
-
|
24
|
+
## Without `Gemfile`
|
26
25
|
|
27
|
-
|
26
|
+
On your command line run the following:
|
28
27
|
|
29
|
-
|
28
|
+
gem install 'rulezilla'
|
30
29
|
|
31
|
-
|
30
|
+
## Usage
|
32
31
|
|
33
|
-
|
32
|
+
### Rules
|
34
33
|
|
34
|
+
Rules are defined in Ruby. Rules are classes that include the `Rulezilla::DSL`.
|
35
35
|
|
36
36
|
#### Ruby
|
37
37
|
|
38
|
-
|
38
|
+
You can use plain Ruby to define the rule classes. But you will need to include the `Rulezilla::DSL` module. That will give you access to the DSL used to define rules.
|
39
39
|
|
40
|
-
|
40
|
+
Here is an example:
|
41
41
|
|
42
42
|
class RoboticsRule
|
43
43
|
include Rulezilla::DSL
|
@@ -59,6 +59,8 @@ To use rulezilla, please include `Rulezilla::DSL` in your class:
|
|
59
59
|
|
60
60
|
end
|
61
61
|
|
62
|
+
Please refer to the [feature](spec/features/rulezilla_dsl_framework.feature) for further details of the DSL.
|
63
|
+
|
62
64
|
### Support Module
|
63
65
|
|
64
66
|
The support module will be automatically included if its name is `"#{rule_class_name}Support"`
|
@@ -73,24 +75,28 @@ e.g. if the rule class name is `RoboticsRule`, then the support would be `Roboti
|
|
73
75
|
|
74
76
|
### How to execute the rule
|
75
77
|
|
76
|
-
|
78
|
+
If the entity is:
|
77
79
|
|
78
|
-
{
|
79
|
-
not_injure_human?:
|
80
|
-
do_as_human_told?:
|
81
|
-
in_danger?:
|
80
|
+
entity = {
|
81
|
+
not_injure_human?: true,
|
82
|
+
do_as_human_told?: true,
|
83
|
+
in_danger?: true,
|
82
84
|
not_letting_itself_be_detroyed?: true
|
83
85
|
}
|
84
86
|
|
85
|
-
#### To get the first matching result
|
87
|
+
#### To get the first matching result output
|
86
88
|
|
87
89
|
RoboticsRule.apply(entity) #=> true
|
88
90
|
|
89
|
-
#### To get all matching
|
91
|
+
#### To get all matching result outputs
|
90
92
|
|
91
|
-
RoboticsRule.all(entity) #=> [true]
|
93
|
+
RoboticsRule.all(entity) #=> [true, false]
|
94
|
+
|
95
|
+
Note that `false` is the result outcome coming out from `default(false)` on top level, which is also called `root node`. The `root` node does not have any condition and hence
|
96
|
+
it is considered to be matching. This means, by consequence, that its result (`default(false)`) is included in the list of matching result outputs which `#all(entity)` above
|
97
|
+
returns.
|
92
98
|
|
93
|
-
#### To get the trace of all
|
99
|
+
#### To get the trace of all nodes
|
94
100
|
|
95
101
|
RoboticsRule.trace(entity)
|
96
102
|
#=> all the nodes instance: [root, may_not_injure_human, obey_human, protect_its_own_existence] in sequence order.
|
@@ -100,10 +106,10 @@ if the entity is:
|
|
100
106
|
RoboticsRule.results #=> [true, false]
|
101
107
|
|
102
108
|
|
103
|
-
|
109
|
+
### Syntax
|
104
110
|
|
105
111
|
Please refer to the features for DSL syntax:
|
106
112
|
|
107
|
-
[DSL Feature](spec/features/
|
113
|
+
[DSL Feature](spec/features/rulezilla_dsl_framework.feature),
|
108
114
|
|
109
115
|
[Default Support Methods Feature](spec/features/default_support_methods.feature)
|
data/catalog-info.yaml
ADDED
data/lib/rulezilla/dsl.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rulezilla
|
2
4
|
module DSL
|
3
5
|
def self.included(base)
|
@@ -20,7 +22,11 @@ module Rulezilla
|
|
20
22
|
|
21
23
|
klass.class_eval do
|
22
24
|
include Rulezilla::BasicSupport
|
23
|
-
|
25
|
+
begin
|
26
|
+
include Object.const_get("#{klass_name}Support")
|
27
|
+
rescue StandardError
|
28
|
+
NameError
|
29
|
+
end
|
24
30
|
|
25
31
|
attr_reader :record
|
26
32
|
|
@@ -42,24 +48,24 @@ module Rulezilla
|
|
42
48
|
@mandatory_attributes ||= []
|
43
49
|
end
|
44
50
|
|
45
|
-
def apply(record={})
|
51
|
+
def apply(record = {})
|
46
52
|
result_node = trace(record).last
|
47
53
|
|
48
54
|
result_node.nil? ? nil : result_node.result(record_klass_instance(record))
|
49
55
|
end
|
50
56
|
|
51
|
-
def all(record={})
|
57
|
+
def all(record = {})
|
52
58
|
validate_missing_attributes(record)
|
53
59
|
result_node = tree.find_all(record_klass_instance(record))
|
54
60
|
|
55
61
|
result_node.nil? ? nil : result_node.map { |node| node.result(record_klass_instance(record)) }
|
56
62
|
end
|
57
63
|
|
58
|
-
def results(record=nil)
|
64
|
+
def results(record = nil)
|
59
65
|
tree.all_results(record_klass_instance(record)).uniq
|
60
66
|
end
|
61
67
|
|
62
|
-
def trace(record=nil)
|
68
|
+
def trace(record = nil)
|
63
69
|
validate_missing_attributes(record)
|
64
70
|
|
65
71
|
tree.trace(record_klass_instance(record))
|
@@ -74,22 +80,29 @@ module Rulezilla
|
|
74
80
|
end
|
75
81
|
|
76
82
|
def tree
|
77
|
-
@tree ||= Tree.new(Node.new
|
83
|
+
@tree ||= Tree.new(Node.new)
|
78
84
|
end
|
79
85
|
|
80
86
|
private
|
81
87
|
|
82
88
|
def record_klass_instance(record)
|
83
|
-
Object.const_get("#{
|
89
|
+
Object.const_get("#{name}Record").new(record)
|
84
90
|
end
|
85
91
|
|
86
92
|
def missing_attributes(record)
|
87
|
-
|
88
|
-
|
93
|
+
record_attributes = if record.is_a?(Hash) || record.is_a?(OpenStruct)
|
94
|
+
record.to_h.keys.map(&:to_sym)
|
95
|
+
else
|
96
|
+
record.methods
|
97
|
+
end
|
98
|
+
|
99
|
+
mandatory_attributes.map(&:to_sym) - record_attributes
|
89
100
|
end
|
90
101
|
|
91
102
|
def validate_missing_attributes(record)
|
92
|
-
|
103
|
+
unless missing_attributes(record).empty?
|
104
|
+
raise "Missing #{missing_attributes(record).join(', ')} attributes from: #{record}"
|
105
|
+
end
|
93
106
|
end
|
94
107
|
|
95
108
|
# DSL methods
|
@@ -97,22 +110,22 @@ module Rulezilla
|
|
97
110
|
@mandatory_attributes = mandatory_attributes | fields
|
98
111
|
end
|
99
112
|
|
100
|
-
def define(name=nil, &block)
|
113
|
+
def define(name = nil, &block)
|
101
114
|
tree.create_and_move_to_child(name)
|
102
115
|
|
103
116
|
instance_eval(&block)
|
104
117
|
tree.go_up
|
105
118
|
end
|
106
|
-
|
119
|
+
alias group define
|
107
120
|
|
108
121
|
def condition(&block)
|
109
122
|
tree.current_node.condition = block
|
110
123
|
end
|
111
124
|
|
112
|
-
def result(value=nil, &block)
|
125
|
+
def result(value = nil, &block)
|
113
126
|
tree.current_node.result = value.nil? ? block : value
|
114
127
|
end
|
115
|
-
|
128
|
+
alias default result
|
116
129
|
|
117
130
|
# End of DSL methods
|
118
131
|
end
|
data/lib/rulezilla/node.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rulezilla
|
2
4
|
class Node
|
3
|
-
attr_accessor :
|
4
|
-
|
5
|
+
attr_accessor :children,
|
6
|
+
:condition,
|
7
|
+
:parent
|
8
|
+
|
9
|
+
attr_reader :default, :name
|
10
|
+
attr_writer :result
|
5
11
|
|
6
12
|
def initialize
|
7
13
|
@children = []
|
@@ -17,25 +23,18 @@ module Rulezilla
|
|
17
23
|
|
18
24
|
def applies?(record)
|
19
25
|
return true if condition.nil?
|
20
|
-
|
26
|
+
|
27
|
+
!!record.instance_eval(&condition)
|
21
28
|
end
|
22
29
|
|
23
30
|
def result(record)
|
24
31
|
@result.is_a?(Proc) ? record.instance_eval(&@result) : @result
|
25
32
|
end
|
26
33
|
|
27
|
-
def condition=(block)
|
28
|
-
@condition = block
|
29
|
-
end
|
30
|
-
|
31
34
|
def name=(value)
|
32
35
|
@name = value.to_s
|
33
36
|
end
|
34
37
|
|
35
|
-
def result=(block)
|
36
|
-
@result = block
|
37
|
-
end
|
38
|
-
|
39
38
|
def add_child(node)
|
40
39
|
node.parent = self
|
41
40
|
children << node
|