rulebook 0.2.1 → 0.3.0
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.
- data/README.md +37 -26
- data/TODO +0 -1
- data/VERSION +1 -1
- data/lib/rulebook.rb +44 -18
- data/rulebook.gemspec +3 -2
- data/test/helper.rb +2 -2
- data/test/test_rules.rb +90 -0
- data/test/test_user.rb +10 -7
- metadata +5 -4
data/README.md
CHANGED
@@ -9,7 +9,7 @@ Allows you to define a set of 'rules' or dynamic methods to apply to a class.
|
|
9
9
|
|
10
10
|
## _Notice_
|
11
11
|
|
12
|
-
The format
|
12
|
+
The format is _back_ to what it was before 0.2.2!
|
13
13
|
|
14
14
|
## Simple Example
|
15
15
|
|
@@ -20,14 +20,12 @@ The format has changed since version 0.1.1. Check out the example below:
|
|
20
20
|
@name = name
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
puts "#{@name} says '#{what_to_say.gsub(/_/, ' ')}'"
|
26
|
-
end
|
23
|
+
rule /say_(.+)/ do |what_to_say|
|
24
|
+
puts "#{@name} says '#{what_to_say.gsub(/_/, ' ')}'"
|
27
25
|
end
|
28
26
|
end
|
29
27
|
|
30
|
-
User.new('Ryan').say_hello_world # =>
|
28
|
+
User.new('Ryan').say_hello_world # => Ryan says 'hello world'
|
31
29
|
|
32
30
|
## How It Works
|
33
31
|
|
@@ -49,10 +47,8 @@ There is also a method called `class_rules` which does the same as rules does, o
|
|
49
47
|
@title = :user
|
50
48
|
end
|
51
49
|
|
52
|
-
|
53
|
-
|
54
|
-
@title = title.to_sym
|
55
|
-
end
|
50
|
+
rule /is_(admin|moderator|super_user|user)/ do |title|
|
51
|
+
@title = title.to_sym
|
56
52
|
end
|
57
53
|
end
|
58
54
|
|
@@ -77,6 +73,8 @@ You can now do things like
|
|
77
73
|
|
78
74
|
## Class Methods Example
|
79
75
|
|
76
|
+
require 'rulebook'
|
77
|
+
|
80
78
|
class Car
|
81
79
|
attr :make, :model
|
82
80
|
|
@@ -84,10 +82,8 @@ You can now do things like
|
|
84
82
|
@make, @model = make.capitalize, model.capitalize
|
85
83
|
end
|
86
84
|
|
87
|
-
|
88
|
-
|
89
|
-
new(make, model)
|
90
|
-
end
|
85
|
+
class_rule /new_([a-z]+)_(.+)/ do |make, model|
|
86
|
+
new(make, model)
|
91
87
|
end
|
92
88
|
end
|
93
89
|
|
@@ -97,25 +93,40 @@ You can now do things like
|
|
97
93
|
Car.new_volkswagen_beetle
|
98
94
|
]
|
99
95
|
|
100
|
-
my_cars.first.make # => "Honda"
|
101
|
-
my_cars.first.model # => "Accord"
|
96
|
+
p my_cars.first.make # => "Honda"
|
97
|
+
p my_cars.first.model # => "Accord"
|
102
98
|
|
103
99
|
### Now lets add some instance rules
|
104
100
|
|
105
101
|
class Car
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
true
|
110
|
-
else
|
111
|
-
false
|
112
|
-
end
|
113
|
-
end
|
102
|
+
rule /is_(.+)\?/ do |make_or_model|
|
103
|
+
make_or_model.capitalize!
|
104
|
+
@make == make_or_model || @model == make_or_model
|
114
105
|
end
|
115
106
|
end
|
107
|
+
|
108
|
+
p my_cars.first.is_honda? # => true
|
109
|
+
p my_cars.first.is_beetle? # => false
|
110
|
+
|
111
|
+
## Using outside of class block
|
112
|
+
|
113
|
+
Since `rule` and `class_rule` are both class methods,
|
114
|
+
you can call them all outside of a class block:
|
115
|
+
|
116
|
+
Car.rule(...){}
|
117
|
+
Car.class_rule(...){}
|
118
|
+
|
119
|
+
Since 0.2 you can call the class methods `rules` and `class_rules` to wrap your rules in a block:
|
120
|
+
|
121
|
+
Car.rules do
|
122
|
+
rule(...){}
|
123
|
+
end
|
124
|
+
|
125
|
+
Car.class_rules do
|
126
|
+
rule(...){}
|
127
|
+
end
|
116
128
|
|
117
|
-
|
118
|
-
my_cars.first.is_beetle? # => false
|
129
|
+
The result is exactly the same.
|
119
130
|
|
120
131
|
#### There are more examples in the examples and [test][1] directories and [Rubular][2] is a great place to test your Regexp.
|
121
132
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/rulebook.rb
CHANGED
@@ -3,7 +3,9 @@ class RuleBook
|
|
3
3
|
attr :what_to_capture, :block
|
4
4
|
|
5
5
|
def initialize(what_to_capture, &block)
|
6
|
-
raise(TypeError, 'what_to_capture must be of type Regexp')
|
6
|
+
raise(TypeError, 'what_to_capture must be of type Regexp') \
|
7
|
+
unless what_to_capture.is_a?(Regexp)
|
8
|
+
|
7
9
|
@what_to_capture, @block = what_to_capture, block
|
8
10
|
end
|
9
11
|
|
@@ -36,12 +38,12 @@ class RuleBook
|
|
36
38
|
end
|
37
39
|
|
38
40
|
class RuleBook
|
39
|
-
module
|
40
|
-
def method_missing(meth, *args, &
|
41
|
+
module IncludeMethods
|
42
|
+
def method_missing(meth, *args, &block)
|
41
43
|
rulebook = self.class.const_get('INSTANCE_RULEBOOK')
|
42
44
|
rules = rulebook.find_rules_that_match_against(meth)
|
43
45
|
|
44
|
-
unless rules.nil?
|
46
|
+
unless rules.nil? || rules.empty?
|
45
47
|
rule = rules.first
|
46
48
|
match = rule.match_against(meth)
|
47
49
|
instance_exec(*match.captures, *args, &rule.block)
|
@@ -51,8 +53,8 @@ class RuleBook
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
|
-
module
|
55
|
-
def method_missing(meth, *args, &
|
56
|
+
module ExtendMethods
|
57
|
+
def method_missing(meth, *args, &block)
|
56
58
|
rulebook = const_get('CLASS_NOTEBOOK')
|
57
59
|
rules = rulebook.find_rules_that_match_against(meth)
|
58
60
|
|
@@ -68,23 +70,47 @@ class RuleBook
|
|
68
70
|
end
|
69
71
|
|
70
72
|
class Module
|
71
|
-
def
|
73
|
+
def rule(what_to_capture, &block)
|
72
74
|
raise(ArgumentError, 'rules must have a block') unless block_given?
|
73
|
-
unless const_defined?('INSTANCE_RULEBOOK')
|
74
|
-
const_set('INSTANCE_RULEBOOK', RuleBook.new)
|
75
|
-
include RuleBook::InstanceMethods
|
76
|
-
end
|
77
75
|
|
78
|
-
|
76
|
+
setup_rulebook('INSTANCE_RULEBOOK', :include)
|
77
|
+
const_get('INSTANCE_RULEBOOK').rule(what_to_capture, &block)
|
79
78
|
end
|
80
79
|
|
81
|
-
def
|
80
|
+
def class_rule(what_to_capture, &block)
|
81
|
+
raise(ArgumentError, 'class_rules must have a block') unless block_given?
|
82
|
+
|
83
|
+
setup_rulebook('CLASS_NOTEBOOK', :extend)
|
84
|
+
const_get('CLASS_NOTEBOOK').rule(what_to_capture, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
def rules(&block)
|
88
|
+
raise(ArgumentError, 'rules must have a block') unless block_given?
|
89
|
+
|
90
|
+
setup_rulebook('INSTANCE_RULEBOOK', :include)
|
91
|
+
const_get('INSTANCE_RULEBOOK').instance_eval(&block)
|
92
|
+
const_get('INSTANCE_RULEBOOK')
|
93
|
+
end
|
94
|
+
|
95
|
+
def class_rules(&block)
|
82
96
|
raise(ArgumentError, 'class_rules must have a block') unless block_given?
|
83
|
-
unless const_defined?('CLASS_NOTEBOOK')
|
84
|
-
const_set('CLASS_NOTEBOOK', RuleBook.new)
|
85
|
-
extend RuleBook::ClassMethods
|
86
|
-
end
|
87
97
|
|
88
|
-
|
98
|
+
setup_rulebook('CLASS_NOTEBOOK', :extend)
|
99
|
+
const_get('CLASS_NOTEBOOK').instance_eval(&block)
|
100
|
+
const_get('CLASS_NOTEBOOK')
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def setup_rulebook(rulebook_constant, extend_or_include)
|
106
|
+
raise(ArgumentError, 'extend_or_include must be :extend or :include') \
|
107
|
+
unless [:extend, :include].include?(extend_or_include)
|
108
|
+
|
109
|
+
unless const_defined?(rulebook_constant)
|
110
|
+
const_set(rulebook_constant, RuleBook.new)
|
111
|
+
|
112
|
+
module_name = extend_or_include.to_s.capitalize + 'Methods'
|
113
|
+
send(extend_or_include, RuleBook.const_get(module_name))
|
114
|
+
end
|
89
115
|
end
|
90
116
|
end
|
data/rulebook.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rulebook}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Ryan Lewis"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-29}
|
13
13
|
s.description = %q{Lets you define methods with regex for dynamic methods}
|
14
14
|
s.email = %q{c00lryguy@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
|
|
42
42
|
"test/helper.rb",
|
43
43
|
"test/test_chevy.rb",
|
44
44
|
"test/test_class_methods.rb",
|
45
|
+
"test/test_rules.rb",
|
45
46
|
"test/test_ryguy.rb",
|
46
47
|
"test/test_user.rb"
|
47
48
|
]
|
data/test/helper.rb
CHANGED
data/test/test_rules.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
class TestRule < Test::Unit::TestCase
|
5
|
+
class User
|
6
|
+
attr_accessor :name, :gender, :height, :eye_color, :date_of_birth, :age
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
class User
|
11
|
+
def User.list
|
12
|
+
@@list ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
User.list << self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Instance Rules
|
21
|
+
class User
|
22
|
+
rule(/is_your_name_([a-z_]+)\?/) do |name|
|
23
|
+
@name.capitalize == name.capitalize
|
24
|
+
end
|
25
|
+
|
26
|
+
rules do
|
27
|
+
rule(/is_(male|female)\?/) do |gender|
|
28
|
+
@gender == gender.to_sym
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
User.rule(/was_born_([a-z]+_\d+(st|nd|rd|th)?_\d+)/) do |date_of_birth|
|
34
|
+
@date_of_birth = Date.parse(date_of_birth.gsub(/_/, ' '))
|
35
|
+
@age = (Date.today - @date_of_birth).to_i / 365
|
36
|
+
end
|
37
|
+
|
38
|
+
User.rules do
|
39
|
+
rule(/is_(\d+)\?/) do |age|
|
40
|
+
@age == age.to_i
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Class Rules
|
45
|
+
# TODO: two more
|
46
|
+
class User
|
47
|
+
class_rule(/new_(male|female)/) do |gender|
|
48
|
+
instance = new
|
49
|
+
instance.gender = gender.to_sym
|
50
|
+
instance
|
51
|
+
end
|
52
|
+
|
53
|
+
class_rules do
|
54
|
+
rule(/find_(males|females)/) do |gender|
|
55
|
+
list.find_all { |user| user.gender == gender.to_sym }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
context 'Ryan' do
|
62
|
+
setup do
|
63
|
+
@user = User.new_male
|
64
|
+
@user.name = 'Ryan'
|
65
|
+
@user.was_born_jan_15_1991
|
66
|
+
end
|
67
|
+
|
68
|
+
should 'answer yes to all obvious questions' do
|
69
|
+
assert @user.is_your_name_ryan?
|
70
|
+
assert @user.is_male?
|
71
|
+
assert @user.is_19?
|
72
|
+
end
|
73
|
+
|
74
|
+
should 'answer no to all silly questions' do
|
75
|
+
refute @user.is_your_name_mark?
|
76
|
+
refute @user.is_female?
|
77
|
+
refute @user.is_21?
|
78
|
+
end
|
79
|
+
|
80
|
+
teardown do
|
81
|
+
@user = nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'User list' do
|
86
|
+
should 'should have any females' do
|
87
|
+
assert User.find_females.length == 0
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/test/test_user.rb
CHANGED
@@ -1,15 +1,18 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'date'
|
3
|
-
|
3
|
+
|
4
4
|
class TestUser < Test::Unit::TestCase
|
5
|
+
|
6
|
+
class User
|
7
|
+
attr_accessor :name, :gender, :height, :eye_color, :date_of_birth, :age
|
8
|
+
end
|
9
|
+
|
5
10
|
class User
|
6
|
-
|
11
|
+
rule(/is_(male|female)/) do |gender|
|
12
|
+
@gender = gender.to_sym
|
13
|
+
end
|
7
14
|
|
8
15
|
rules do
|
9
|
-
rule(/is_(male|female)/) do |gender|
|
10
|
-
@gender = gender.to_sym
|
11
|
-
end
|
12
|
-
|
13
16
|
rule(/is_(\d+)_foot_(\d+)(_inches)?/) do |feet, inches|
|
14
17
|
@height = "#{feet}-#{inches}"
|
15
18
|
end
|
@@ -24,7 +27,7 @@ class TestUser < Test::Unit::TestCase
|
|
24
27
|
end
|
25
28
|
end
|
26
29
|
end
|
27
|
-
|
30
|
+
|
28
31
|
context 'A User instance' do
|
29
32
|
setup do
|
30
33
|
@ryguy = User.new
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ryan Lewis
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-29 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -77,5 +77,6 @@ test_files:
|
|
77
77
|
- test/helper.rb
|
78
78
|
- test/test_chevy.rb
|
79
79
|
- test/test_class_methods.rb
|
80
|
+
- test/test_rules.rb
|
80
81
|
- test/test_ryguy.rb
|
81
82
|
- test/test_user.rb
|