ruva 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://secure.travis-ci.org/ssmm/ruva.png)](http://travis-ci.org/ssmm/ruva)
|
3
|
+
[![Build Status](https://secure.travis-ci.org/ssmm/ruva.png)](http://travis-ci.org/ssmm/ruva)
|
4
4
|
[![Code Climate](https://codeclimate.com/badge.png)](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
|