rulezilla 0.1.4 → 0.1.5

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
  SHA1:
3
- metadata.gz: 0a5437383cf683007f42c90a096f3428103cdc46
4
- data.tar.gz: 0e3366b7fee344c1d5c1958ee1f8ffd54a2b402b
3
+ metadata.gz: 8de468c7423c8fb95e879491361d8587ced03b28
4
+ data.tar.gz: 9cbbd613deab120d67a6da93e81a4e7fc360ec38
5
5
  SHA512:
6
- metadata.gz: abb77e8d80423a511e1ea78a0c4600bb103f628879268033e653573c5e264840aaacebe52512334597853991b9aee9e66b51ea49511c8cb4f7e2e65d58cd4271
7
- data.tar.gz: 2c0100529a1032e5b02b12c522effc33d44cd8753cdfbd3541b9f1d83ab197e5864a098f44eab8238c9347f3657d1e0601d12dc2bf2ea17554b70f1d63fc034d
6
+ metadata.gz: 52adab9a3346e9cfb20b58a7197c2a724f823f04d647f2dc313f07cb01ed169c59c5a10c708fe2581a6c7914da33e88a3641f04b02ce337f8d2207dad181df51
7
+ data.tar.gz: 9fdf3bb8bf2b3366fec2e7d140ade30020113f8e3ef80bdd198720139152e6b3c81a3b816a2c292dcc315e01ed0b26a96687beccfbe25cb848569db8d3d47965
data/.gitignore CHANGED
@@ -1 +1,5 @@
1
1
  .bundle
2
+ Gemfile.lock
3
+ .ruby-version
4
+ .ruby-gemset
5
+ .idea/
data/Gemfile CHANGED
@@ -1,6 +1,2 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
-
4
- gem 'rspec'
5
- gem 'turnip'
6
- gem 'pry'
data/README.md CHANGED
@@ -1,43 +1,61 @@
1
- [![Semaphore](https://semaphoreapp.com/api/v1/projects/e488365d-9c57-4431-916a-72aea091d1b5/229083/shields_badge.png)](https://semaphoreapp.com/simplybusiness/rulezilla)
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 provide a DSL to implement rules for various tasks. In the current version we are still rely user to have a certain level of Ruby knowledge to be able to use this DSL. The ultimate goal is for people without prior Ruby knowledge can change and even write the Rule.
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
- gem 'rulezilla', git: 'git@github.com:simplybusiness/rulezilla.git'
14
+ ## Using `Gemfile`
15
+
16
+ Add the following line to your `Gemfile`:
17
+
18
+ gem 'rulezilla'
19
+
20
+ Then run:
21
+
22
+ bundle install
23
+
24
+ ## Without `Gemfile`
14
25
 
15
- ## Implementation
26
+ On your command line run the following:
27
+
28
+ gem install 'rulezilla'
29
+
30
+ ## Usage
16
31
 
17
32
  ### Rules
18
33
 
34
+ Rules can be defined either using `Gherkin` or pure Ruby. In either case, rules are classes that include the `Rulezilla::DSL`.
35
+
19
36
  #### Gherkin (Beta)
20
37
 
21
- rulezilla Gherkin has only very limited support now
38
+ > *Note:* Currently, rulezilla Gherkin has only very limited support.
22
39
 
23
- First set the path of which rulezilla can load the feature files from:
40
+ Rules are defined inside `.feature` files which should be organized under a specific directory. In order to be able to use these rules, you need to first
41
+ set the path that rulezilla can use in order to load them.
24
42
 
25
- Rulezilla.gherkin_rules_path = 'absolute path'
43
+ Rulezilla.gherkin_rules_path = 'absolute path to folder holding your feature files'
26
44
 
27
- The filename will then converted to the name of the class, e.g. `invalid_number_rule.feature` will generate `Rulezilla::InvalidNumberRule` class
45
+ Rulezilla will load all the feature files and for each one will create a rule class. The filename will be used to build the name of the rule class. For example,
46
+ the file with name `invalid_number_rule.feature` will generate rule class `Rulezilla::InvalidNumberRule`.
28
47
 
29
- We currently only support a very limited steps, please refer to:
48
+ We currently support a very limited type of steps. Please refer to:
30
49
 
31
50
  [True / False](spec/features/gherkin_rules/animal_rule.feature)
32
51
 
33
52
  [Duration](spec/features/gherkin_rules/duration_rule.feature)
34
53
 
35
-
36
54
  #### Ruby
37
55
 
38
- Please refer to the [feature](spec/features/rulezilla_dsl_framwork.feature) for further details
56
+ 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
57
 
40
- To use rulezilla, please include `Rulezilla::DSL` in your class:
58
+ Here is an example:
41
59
 
42
60
  class RoboticsRule
43
61
  include Rulezilla::DSL
@@ -59,6 +77,8 @@ To use rulezilla, please include `Rulezilla::DSL` in your class:
59
77
 
60
78
  end
61
79
 
80
+ Please refer to the [feature](spec/features/rulezilla_dsl_framework.feature) for further details of the DSL.
81
+
62
82
  ### Support Module
63
83
 
64
84
  The support module will be automatically included if its name is `"#{rule_class_name}Support"`
@@ -73,24 +93,28 @@ e.g. if the rule class name is `RoboticsRule`, then the support would be `Roboti
73
93
 
74
94
  ### How to execute the rule
75
95
 
76
- if the entity is:
96
+ If the entity is:
77
97
 
78
- {
79
- not_injure_human?: true,
80
- do_as_human_told?: true,
81
- in_danger?: true,
98
+ entity = {
99
+ not_injure_human?: true,
100
+ do_as_human_told?: true,
101
+ in_danger?: true,
82
102
  not_letting_itself_be_detroyed?: true
83
103
  }
84
104
 
85
- #### To get the first matching result
105
+ #### To get the first matching result output
86
106
 
87
107
  RoboticsRule.apply(entity) #=> true
88
108
 
89
- #### To get all matching results
109
+ #### To get all matching result outputs
90
110
 
91
- RoboticsRule.all(entity) #=> [true]
111
+ RoboticsRule.all(entity) #=> [true, false]
112
+
113
+ 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
114
+ 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
115
+ returns.
92
116
 
93
- #### To get the trace of all node
117
+ #### To get the trace of all nodes
94
118
 
95
119
  RoboticsRule.trace(entity)
96
120
  #=> all the nodes instance: [root, may_not_injure_human, obey_human, protect_its_own_existence] in sequence order.
@@ -100,10 +124,10 @@ if the entity is:
100
124
  RoboticsRule.results #=> [true, false]
101
125
 
102
126
 
103
- # Syntax
127
+ ### Syntax
104
128
 
105
129
  Please refer to the features for DSL syntax:
106
130
 
107
- [DSL Feature](spec/features/rulezilla_dsl_framwork.feature),
131
+ [DSL Feature](spec/features/rulezilla_dsl_framework.feature),
108
132
 
109
133
  [Default Support Methods Feature](spec/features/default_support_methods.feature)
@@ -1,7 +1,11 @@
1
1
  module Rulezilla
2
2
  class Node
3
- attr_accessor :parent, :children
4
- attr_reader :condition, :default, :name
3
+ attr_accessor :children,
4
+ :condition,
5
+ :parent
6
+
7
+ attr_reader :default, :name
8
+ attr_writer :result
5
9
 
6
10
  def initialize
7
11
  @children = []
@@ -17,25 +21,17 @@ module Rulezilla
17
21
 
18
22
  def applies?(record)
19
23
  return true if condition.nil?
20
- record.instance_eval(&condition)
24
+ !!record.instance_eval(&condition)
21
25
  end
22
26
 
23
27
  def result(record)
24
28
  @result.is_a?(Proc) ? record.instance_eval(&@result) : @result
25
29
  end
26
30
 
27
- def condition=(block)
28
- @condition = block
29
- end
30
-
31
31
  def name=(value)
32
32
  @name = value.to_s
33
33
  end
34
34
 
35
- def result=(block)
36
- @result = block
37
- end
38
-
39
35
  def add_child(node)
40
36
  node.parent = self
41
37
  children << node
@@ -12,6 +12,8 @@ module Rulezilla
12
12
  @current_node = is_root? ? @root_node : @current_node.parent
13
13
  end
14
14
 
15
+ # Returns all the result outcomes of all the matching nodes.
16
+ #
15
17
  def find_all(record, node=@root_node)
16
18
  array = []
17
19
  if node.applies?(record)
@@ -21,7 +23,7 @@ module Rulezilla
21
23
 
22
24
  return node.has_result? ? array + [node] : array
23
25
  end
24
- return array
26
+ array
25
27
  end
26
28
 
27
29
  def trace(record, node=@root_node)
@@ -1,3 +1,3 @@
1
1
  module Rulezilla
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
@@ -14,5 +14,9 @@ Gem::Specification.new do |gem|
14
14
  gem.version = Rulezilla::VERSION
15
15
  gem.license = 'MIT'
16
16
 
17
- gem.add_runtime_dependency('gherkin')
17
+ gem.add_runtime_dependency('gherkin', '~> 2.5')
18
+ gem.add_runtime_dependency('rspec')
19
+ gem.add_runtime_dependency('turnip')
20
+ gem.add_development_dependency('pry')
21
+ gem.add_development_dependency('pry-doc')
18
22
  end
@@ -85,7 +85,7 @@ Scenario: If nothing is matched in a group, it will fall to default value of the
85
85
  Then the result is "It is alright"
86
86
 
87
87
 
88
- Scenario: If nothing is matched, and no default is define in the group, it will fall to the next default
88
+ Scenario: If nothing is matched, and no default is defined in the group, it will fall to the next default
89
89
  Given the rule is:
90
90
  """
91
91
  group :group_1 do
@@ -126,7 +126,7 @@ Scenario: If nothing is matched, it will continue to evaluate the next group
126
126
  Then the result is "Bad"
127
127
 
128
128
 
129
- Scenario Outline: It evaluate the rule against a record
129
+ Scenario Outline: It evaluates the rule against a record
130
130
  Given the rule is:
131
131
  """
132
132
  define :fruit do
@@ -185,6 +185,53 @@ Scenario: To get all matching outcomes from a rule
185
185
  """
186
186
  Then all the matching outcomes are "B, C, D, F"
187
187
 
188
+ Scenario: To get all matching outcomes from a rule with root node default result
189
+ Given the rule is:
190
+ """
191
+ group :may_not_injure_human do
192
+ condition { not_injure_human? }
193
+
194
+ group :obey_human do
195
+ condition { do_as_human_told? }
196
+ result(true)
197
+
198
+ define :protect_its_own_existence do
199
+ condition { in_danger? && not_letting_itself_be_detroyed? }
200
+ result(true)
201
+ end
202
+ end
203
+ end
204
+
205
+ default(false)
206
+ """
207
+ When the record has attribute "not_injure_human?" and returns "true"
208
+ When the record has attribute "do_as_human_told?" and returns "true"
209
+ When the record has attribute "in_dangert?" and returns "true"
210
+ When the record has attribute "not_letting_itself_be_detroyed?" and returns "true"
211
+ Then all the matching outcomes are "true, false"
212
+
213
+ Scenario: To get all matching outcomes from a rule without root node default result
214
+ Given the rule is:
215
+ """
216
+ group :may_not_injure_human do
217
+ condition { not_injure_human? }
218
+
219
+ group :obey_human do
220
+ condition { do_as_human_told? }
221
+ result(true)
222
+
223
+ define :protect_its_own_existence do
224
+ condition { in_danger? && not_letting_itself_be_detroyed? }
225
+ result(true)
226
+ end
227
+ end
228
+ end
229
+ """
230
+ When the record has attribute "not_injure_human?" and returns "true"
231
+ When the record has attribute "do_as_human_told?" and returns "true"
232
+ When the record has attribute "in_dangert?" and returns "true"
233
+ When the record has attribute "not_letting_itself_be_detroyed?" and returns "true"
234
+ Then all the matching outcomes are "true"
188
235
 
189
236
  Scenario: Support Module
190
237
  Given the rule class name is "FruitRule"
@@ -227,7 +274,7 @@ Scenario Outline: Validate the presence of attributes
227
274
  | apple, orange | does not | |
228
275
 
229
276
 
230
- Scenario: Rule return nil if no rule is defined Given the rule is:
277
+ Scenario: Rule return nil if no rule is defined
231
278
  Given the rule is:
232
279
  """
233
280
  """
@@ -90,7 +90,7 @@ step 'all the outcomes are :outcomes' do |outcomes|
90
90
  end
91
91
 
92
92
  step 'all the matching outcomes are :outcomes' do |outcomes|
93
- outcomes = outcomes.split(',').map(&:strip)
93
+ outcomes = outcomes.split(',').map(&:strip).map {|o| o == 'true' ? true : (o == 'false' ? false : o)}
94
94
  expect(@rule_klass.all(@record)).to match_array outcomes
95
95
  end
96
96
 
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rulezilla
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Wu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-19 00:00:00.000000000 Z
11
+ date: 2016-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gherkin
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - ">="
@@ -24,6 +38,48 @@ dependencies:
24
38
  - - ">="
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: turnip
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-doc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
27
83
  description: Rules DSL
28
84
  email:
29
85
  - peter.wu@simplybusiness.com
@@ -34,7 +90,6 @@ files:
34
90
  - ".gitignore"
35
91
  - ".rspec"
36
92
  - Gemfile
37
- - Gemfile.lock
38
93
  - README.md
39
94
  - lib/rulezilla.rb
40
95
  - lib/rulezilla/basic_support.rb
@@ -50,7 +105,7 @@ files:
50
105
  - spec/features/gherkin_dsl_framework.feature
51
106
  - spec/features/gherkin_rules/animal_rule.feature
52
107
  - spec/features/gherkin_rules/duration_rule.feature
53
- - spec/features/rulezilla_dsl_framwork.feature
108
+ - spec/features/rulezilla_dsl_framework.feature
54
109
  - spec/features/step_definitions/rule_steps.rb
55
110
  - spec/features/step_definitions/rulezilla_dsl_framework_steps.rb
56
111
  - spec/spec_helper.rb
@@ -1,44 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- rulezilla (0.1.4)
5
- gherkin
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- coderay (1.1.0)
11
- diff-lcs (1.2.5)
12
- gherkin (2.12.2)
13
- multi_json (~> 1.3)
14
- method_source (0.8.2)
15
- multi_json (1.10.1)
16
- pry (0.9.12.6)
17
- coderay (~> 1.0)
18
- method_source (~> 0.8)
19
- slop (~> 3.4)
20
- rspec (3.0.0)
21
- rspec-core (~> 3.0.0)
22
- rspec-expectations (~> 3.0.0)
23
- rspec-mocks (~> 3.0.0)
24
- rspec-core (3.0.3)
25
- rspec-support (~> 3.0.0)
26
- rspec-expectations (3.0.3)
27
- diff-lcs (>= 1.2.0, < 2.0)
28
- rspec-support (~> 3.0.0)
29
- rspec-mocks (3.0.3)
30
- rspec-support (~> 3.0.0)
31
- rspec-support (3.0.3)
32
- slop (3.5.0)
33
- turnip (1.2.2)
34
- gherkin (>= 2.5)
35
- rspec (>= 2.0, < 4.0)
36
-
37
- PLATFORMS
38
- ruby
39
-
40
- DEPENDENCIES
41
- pry
42
- rspec
43
- rulezilla!
44
- turnip