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 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