rulebook 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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 has changed since version 0.1.1. Check out the example below:
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
- rules do
24
- rule /say_(.+)/ do |what_to_say|
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 # => "Ryan says '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
- rules do
53
- rule /is_(admin|moderator|super_user|user)/ do |title|
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
- class_rules do
88
- rule /new_([a-z]+)_(.+)/ do |make, model|
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
- rules do
107
- rule /is_(.+)\?/ do |make_or_model|
108
- if @make == make_or_model || @model == make_or_model
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
- my_cars.first.is_honda? # => true
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/TODO CHANGED
@@ -1,2 +1 @@
1
- # Support for class methods
2
1
  # Named captures in Regexp
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
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') unless what_to_capture.is_a?(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 InstanceMethods
40
- def method_missing(meth, *args, &blk)
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 ClassMethods
55
- def method_missing(meth, *args, &blk)
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 rules(&blk)
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
- const_get('INSTANCE_RULEBOOK').instance_eval(&blk)
76
+ setup_rulebook('INSTANCE_RULEBOOK', :include)
77
+ const_get('INSTANCE_RULEBOOK').rule(what_to_capture, &block)
79
78
  end
80
79
 
81
- def class_rules(&blk)
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
- const_get('CLASS_NOTEBOOK').instance_eval(&blk)
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.2.1"
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-27}
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
@@ -8,5 +8,5 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
8
  require 'rulebook'
9
9
 
10
10
  class Test::Unit::TestCase
11
-
12
- end
11
+
12
+ end
@@ -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
- attr :gender, :height, :eye_color, :date_of_birth, :age
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
- - 2
8
- - 1
9
- version: 0.2.1
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-27 00:00:00 -04:00
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