ruva 1.0.1 → 1.0.2
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 +7 -0
- data/.gitignore +1 -0
- data/README.md +7 -7
- data/lib/ruva.rb +48 -30
- data/lib/ruva/expression/equal_greater_less.rb +59 -55
- data/lib/ruva/expression/expression_leaf_spec.rb +37 -46
- data/lib/ruva/expression/identifier_comparable.rb +55 -51
- data/lib/ruva/expression/is_between.rb +49 -45
- data/lib/ruva/expression/matches.rb +39 -35
- data/lib/ruva/expression/ruva_expression.citrus +42 -42
- data/lib/ruva/specification/specification.rb +83 -100
- data/lib/ruva/util.rb +28 -0
- data/lib/ruva/version.rb +1 -1
- data/ruva.gemspec +4 -4
- data/spec/expression_spec.rb +18 -19
- data/spec/hash_to_ostruct_spec.rb +22 -22
- data/spec/helpers/expression_helper.rb +1 -1
- data/spec/util_spec.rb +7 -0
- metadata +15 -22
- data/lib/ruva/expression.rb +0 -17
- data/lib/ruva/specification.rb +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6c530bba26d5669fea221b939d1417aeeaec623e
|
4
|
+
data.tar.gz: 028fee7187edc8839720c561e6faf534416b651e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 14deefe0790aabea2980c6bfe4bc6a805fbcdce6ebed0b4570f4879d732b23c27a89774acfa0e91f45d35be2881c2e184651fd3c2d295be0eedbb4f83f6883df
|
7
|
+
data.tar.gz: cf9a259f1e92df62934d8156b11e83fc2edd09e17e91b2ee6556722a89670ae6ed7fb709d80b51cc148950821bb7e50e8ab2fb7cc43c8468d965736cda9d8317
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Ruva
|
2
2
|
|
3
|
-
[](http://travis-ci.org/ssmm/ruva)
|
3
|
+
[](http://travis-ci.org/ssmm/ruva)
|
4
4
|
[](https://codeclimate.com/github/ssmm/ruva)
|
5
5
|
|
6
|
-
|
6
|
+
Write plain text conditions.
|
7
7
|
|
8
8
|
Assume you have an object called `person` with an attribute `age = 23`:
|
9
9
|
|
@@ -12,10 +12,10 @@ person = OpenStruct.new
|
|
12
12
|
person.age = 23
|
13
13
|
```
|
14
14
|
|
15
|
-
You write
|
15
|
+
You write
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
person.if "age is 23" do
|
18
|
+
person.if "age is 23" do
|
19
19
|
stuff
|
20
20
|
end
|
21
21
|
```
|
@@ -77,7 +77,7 @@ person.if "
|
|
77
77
|
end
|
78
78
|
```
|
79
79
|
|
80
|
-
The above definition says, that the condition is met if any of the three conditions defined under the
|
80
|
+
The above definition says, that the condition is met if any of the three conditions defined under the
|
81
81
|
`any` keyword meet.
|
82
82
|
|
83
83
|
Currently supported are the keywords `all`, `any` and `none`.
|
@@ -97,8 +97,8 @@ Then you load it:
|
|
97
97
|
condition = Ruva.read "your_condition"
|
98
98
|
```
|
99
99
|
|
100
|
-
At this point, ruva loads the condition into some kind of hirarchy, according to the
|
101
|
-
[Specification pattern](http://en.wikipedia.org/wiki/Specification_pattern), and you can invoke its
|
100
|
+
At this point, ruva loads the condition into some kind of hirarchy, according to the
|
101
|
+
[Specification pattern](http://en.wikipedia.org/wiki/Specification_pattern), and you can invoke its
|
102
102
|
`evaluate` method to test any object you want against that condition:
|
103
103
|
|
104
104
|
```ruby
|
data/lib/ruva.rb
CHANGED
@@ -1,7 +1,25 @@
|
|
1
|
+
require 'date'
|
2
|
+
require "ruva/version"
|
3
|
+
require "ruva/util"
|
4
|
+
require 'ruva/specification/specification'
|
5
|
+
require 'ruva/expression/expression_leaf_spec'
|
6
|
+
require 'ruva/expression/equal_greater_less'
|
7
|
+
require 'ruva/expression/identifier_comparable'
|
8
|
+
require 'ruva/expression/is_between'
|
9
|
+
require 'ruva/expression/matches'
|
10
|
+
|
1
11
|
require 'indentation-parser'
|
12
|
+
require 'citrus'
|
13
|
+
require 'ostruct'
|
2
14
|
|
3
|
-
require
|
4
|
-
|
15
|
+
Citrus.require 'ruva/expression/ruva_expression'
|
16
|
+
|
17
|
+
module Ruva::Expression::RuvaExpression
|
18
|
+
def self.parse expression
|
19
|
+
result = super expression
|
20
|
+
result.value
|
21
|
+
end
|
22
|
+
end
|
5
23
|
|
6
24
|
class Object
|
7
25
|
def if condition
|
@@ -18,39 +36,39 @@ module Ruva
|
|
18
36
|
def self.read file
|
19
37
|
interpret IO.read("#{file}.ruva")
|
20
38
|
end
|
21
|
-
|
39
|
+
|
22
40
|
def self.interpret text
|
23
|
-
|
41
|
+
|
24
42
|
parser = IndentationParser.new do |p|
|
25
|
-
p.on /^all$/ do |parent, source, captures|
|
26
|
-
node = AndSpec.new
|
43
|
+
p.on /^all$/ do |parent, source, captures|
|
44
|
+
node = Specification::AndSpec.new
|
27
45
|
parent.append node
|
28
46
|
node
|
29
47
|
end
|
30
|
-
|
31
|
-
p.on /^any$/ do |parent, source, captures|
|
32
|
-
node = OrSpec.new
|
48
|
+
|
49
|
+
p.on /^any$/ do |parent, source, captures|
|
50
|
+
node = Specification::OrSpec.new
|
33
51
|
parent.append node
|
34
52
|
node
|
35
53
|
end
|
36
|
-
|
37
|
-
p.on /^none$/ do |parent, source, captures|
|
38
|
-
node = NotSpec.new
|
54
|
+
|
55
|
+
p.on /^none$/ do |parent, source, captures|
|
56
|
+
node = Specification::NotSpec.new
|
39
57
|
parent.append node
|
40
58
|
node
|
41
59
|
end
|
42
|
-
|
60
|
+
|
43
61
|
p.else do |parent, source|
|
44
|
-
node = RuvaExpression.parse(source)
|
62
|
+
node = Ruva::Expression::RuvaExpression.parse(source)
|
45
63
|
parent.append node
|
46
64
|
node
|
47
65
|
end
|
48
66
|
end
|
49
|
-
|
50
|
-
spec = parser.read(text, AndSpec.new)
|
67
|
+
|
68
|
+
spec = parser.read(text, Specification::AndSpec.new)
|
51
69
|
spec.value
|
52
70
|
end
|
53
|
-
|
71
|
+
|
54
72
|
def self.normalize_indentation str
|
55
73
|
if str.index(/^[ ]*$\n/) == 0
|
56
74
|
str.sub!(/^[ ]*$\n/, "")
|
@@ -61,23 +79,23 @@ module Ruva
|
|
61
79
|
str
|
62
80
|
end
|
63
81
|
|
64
|
-
def self.hash_to_ostruct hash
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
-
|
82
|
+
# def self.hash_to_ostruct hash
|
83
|
+
# ostruct = OpenStruct.new
|
84
|
+
# hash.each do |key, value|
|
85
|
+
# if value.is_a? Hash
|
86
|
+
# ostruct.send("#{key}=", hash_to_ostruct(value))
|
87
|
+
# else
|
88
|
+
# ostruct.send("#{key}=", value)
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
# ostruct
|
92
|
+
# end
|
93
|
+
|
76
94
|
class Else
|
77
95
|
def initialize satisfied
|
78
96
|
@satisfied = satisfied
|
79
97
|
end
|
80
|
-
def else
|
98
|
+
def else
|
81
99
|
raise unless block_given?
|
82
100
|
yield unless @satisfied
|
83
101
|
end
|
@@ -1,61 +1,65 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
|
8
|
-
def compare (comparable, value) value < comparable end
|
9
|
-
def satisfied_text() "less than" end
|
10
|
-
def unsatisfied_text() "greater than" end
|
11
|
-
end
|
12
|
-
|
13
|
-
class GreaterEqualSpec < ExpressionLeafSpec
|
14
|
-
def compare (comparable, value) value >= comparable end
|
15
|
-
def satisfied_text() "greater than or equal to" end
|
16
|
-
def unsatisfied_text() "less than" end
|
17
|
-
end
|
18
|
-
|
19
|
-
class LessEqualSpec < ExpressionLeafSpec
|
20
|
-
def compare (comparable, value) value <= comparable end
|
21
|
-
def satisfied_text() "less than or equal to" end
|
22
|
-
def unsatisfied_text() "greater than" end
|
23
|
-
end
|
24
|
-
|
25
|
-
module EqualGreaterLess
|
26
|
-
def value
|
27
|
-
spec = create_spec
|
28
|
-
spec.set_validator { |value, *args|
|
29
|
-
compare @comparable, value
|
30
|
-
}
|
31
|
-
spec.set_reporting { |satisfied, value, *args|
|
32
|
-
comparable_string = @comparable.to_s
|
33
|
-
create_report_string "is #{satisfied_text} #{comparable_string}", "is #{unsatisfied_text} #{comparable_string}", satisfied, value
|
34
|
-
}
|
35
|
-
spec
|
36
|
-
end
|
37
|
-
end
|
1
|
+
module Ruva
|
2
|
+
module Expression
|
3
|
+
class GreaterSpec < ExpressionLeafSpec
|
4
|
+
def compare (comparable, value) value > comparable end
|
5
|
+
def satisfied_text() "greater than" end
|
6
|
+
def unsatisfied_text() "less than" end
|
7
|
+
end
|
38
8
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
9
|
+
class LessSpec < ExpressionLeafSpec
|
10
|
+
def compare (comparable, value) value < comparable end
|
11
|
+
def satisfied_text() "less than" end
|
12
|
+
def unsatisfied_text() "greater than" end
|
13
|
+
end
|
44
14
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
15
|
+
class GreaterEqualSpec < ExpressionLeafSpec
|
16
|
+
def compare (comparable, value) value >= comparable end
|
17
|
+
def satisfied_text() "greater than or equal to" end
|
18
|
+
def unsatisfied_text() "less than" end
|
19
|
+
end
|
50
20
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
21
|
+
class LessEqualSpec < ExpressionLeafSpec
|
22
|
+
def compare (comparable, value) value <= comparable end
|
23
|
+
def satisfied_text() "less than or equal to" end
|
24
|
+
def unsatisfied_text() "greater than" end
|
25
|
+
end
|
26
|
+
|
27
|
+
module EqualGreaterLess
|
28
|
+
def value
|
29
|
+
spec = create_spec
|
30
|
+
spec.set_validator { |value, *args|
|
31
|
+
compare @comparable, value
|
32
|
+
}
|
33
|
+
spec.set_reporting { |satisfied, value, *args|
|
34
|
+
comparable_string = @comparable.to_s
|
35
|
+
create_report_string "is #{satisfied_text} #{comparable_string}", "is #{unsatisfied_text} #{comparable_string}", satisfied, value
|
36
|
+
}
|
37
|
+
spec
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module Greater include EqualGreaterLess
|
42
|
+
def create_spec
|
43
|
+
GreaterSpec.new(identifier.value, comparable.value)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module Less include EqualGreaterLess
|
48
|
+
def create_spec
|
49
|
+
LessSpec.new(identifier.value, comparable.value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module GreaterOrEqual include EqualGreaterLess
|
54
|
+
def create_spec
|
55
|
+
GreaterEqualSpec.new(identifier.value, comparable.value)
|
56
|
+
end
|
57
|
+
end
|
56
58
|
|
57
|
-
module LessOrEqual include EqualGreaterLess
|
58
|
-
|
59
|
-
|
59
|
+
module LessOrEqual include EqualGreaterLess
|
60
|
+
def create_spec
|
61
|
+
LessEqualSpec.new(identifier.value, comparable.value)
|
62
|
+
end
|
63
|
+
end
|
60
64
|
end
|
61
65
|
end
|
@@ -1,51 +1,42 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
obj = OpenStruct.new obj
|
1
|
+
module Ruva
|
2
|
+
module Expression
|
3
|
+
class ExpressionLeafSpec
|
4
|
+
def get_value value
|
5
|
+
Ruva::Util::DeepCall.init_deep_call(@name, value)
|
7
6
|
end
|
8
|
-
get_object_value @name.split(".").reverse, obj
|
9
|
-
else
|
10
|
-
raise "Unexpected input"
|
11
|
-
end
|
12
|
-
end
|
13
7
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# if (obj.is_a?(Hash))
|
18
|
-
# get_hash_value(key_array, obj)
|
19
|
-
# else
|
20
|
-
# get_object_value(key_array, obj)
|
21
|
-
# end
|
22
|
-
# else
|
23
|
-
# obj = OpenStruct.new hash
|
24
|
-
# obj.instance_eval(key_array.pop)
|
25
|
-
# end
|
26
|
-
# end
|
27
|
-
|
28
|
-
def get_object_value key_array, obj
|
29
|
-
if (key_array.size > 1)
|
30
|
-
obj = obj.instance_eval(key_array.pop)
|
31
|
-
if (obj.is_a?(Hash))
|
32
|
-
obj = OpenStruct.new obj
|
8
|
+
def initialize name, args
|
9
|
+
@name = name
|
10
|
+
@comparable = args
|
33
11
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
12
|
+
|
13
|
+
def set_validator &block
|
14
|
+
@validator = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_reporting &block
|
18
|
+
@reporting = block
|
19
|
+
end
|
20
|
+
|
21
|
+
def evaluate *args
|
22
|
+
instance_exec(get_value(*args), *args, &@validator)
|
23
|
+
end
|
24
|
+
|
25
|
+
# def report satisfied, *args
|
26
|
+
# instance_exec(satisfied, get_value(*args), *args, &@reporting)
|
27
|
+
# end
|
28
|
+
|
29
|
+
# def create_typed_value value
|
30
|
+
# case value
|
31
|
+
# when Numeric then value
|
32
|
+
# when String then "'#{value}'"
|
33
|
+
# else value
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
|
37
|
+
# def create_report_string positive, negative, satisfied, value
|
38
|
+
# @name.to_s + " #{create_typed_value value} " + (satisfied ? positive : negative)
|
39
|
+
# end
|
45
40
|
end
|
46
41
|
end
|
47
|
-
|
48
|
-
def create_report_string positive, negative, satisfied, value
|
49
|
-
@name.to_s + " #{create_typed_value value} " + (satisfied ? positive : negative)
|
50
|
-
end
|
51
|
-
end
|
42
|
+
end
|
@@ -1,53 +1,57 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
1
|
+
module Ruva
|
2
|
+
module Expression
|
3
|
+
module Identifier
|
4
|
+
def value
|
5
|
+
to_s.strip
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Comparable
|
10
|
+
def value
|
11
|
+
to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module LastComparable
|
16
|
+
def value
|
17
|
+
Array.new << comparable
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module IntComparable
|
22
|
+
def value
|
23
|
+
to_i
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module FloatComparable
|
28
|
+
def value
|
29
|
+
to_f
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module DateComparable
|
34
|
+
def value
|
35
|
+
Date.parse to_s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module RegexComparable
|
40
|
+
def value
|
41
|
+
Regexp.new regex.value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module TextComparable
|
46
|
+
def value
|
47
|
+
return to_s.strip
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module Comparables
|
52
|
+
def value
|
53
|
+
subresult.value << comparable
|
54
|
+
end
|
55
|
+
end
|
52
56
|
end
|
53
57
|
end
|