rulebook 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document CHANGED
@@ -1,5 +1,5 @@
1
1
  README.md
2
2
  lib/**/*.rb
3
3
  bin/*
4
- features/**/*.feature
4
+ test/**/*.rb
5
5
  LICENSE
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ gem 'meta_tools'
2
+
3
+ group :development do
4
+ gem 'rake'
5
+ gem 'riot'
6
+ gem 'jeweler'
7
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,21 @@
1
+ GEM
2
+ specs:
3
+ git (1.2.5)
4
+ jeweler (1.5.2)
5
+ bundler (~> 1.0.0)
6
+ git (>= 1.2.5)
7
+ rake
8
+ meta_tools (0.1.0)
9
+ rake (0.8.7)
10
+ riot (0.12.3)
11
+ rr
12
+ rr (1.0.2)
13
+
14
+ PLATFORMS
15
+ x86-mingw32
16
+
17
+ DEPENDENCIES
18
+ jeweler
19
+ meta_tools
20
+ rake
21
+ riot
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Ryan Lewis
1
+ Copyright (c) 2009,2010,2011 Ryan Lewis
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # rulebook
1
+ # rulebook ![](http://stillmaintained.com/c00lryguy/rulebook.png)
2
2
 
3
3
  Allows you to define a set of 'rules' or dynamic methods to apply to a class.
4
4
 
@@ -7,68 +7,56 @@ Allows you to define a set of 'rules' or dynamic methods to apply to a class.
7
7
  > gem update --system
8
8
  > gem install rulebook
9
9
 
10
- ## _Notice_
11
-
12
- The format is _back_ to what it was before 0.2.2!
13
-
14
10
  ## Simple Example
15
11
 
16
12
  require 'rulebook'
17
13
 
18
14
  class User
19
- def initialize(name)
20
- @name = name
21
- end
22
-
23
- rule /say_(.+)/ do |what_to_say|
24
- puts "#{@name} says '#{what_to_say.gsub(/_/, ' ')}'"
25
- end
15
+ follows_the_rules!
16
+
17
+ def initialize(name)
18
+ @name = name
19
+ end
20
+
21
+ rulebook.add /say_(.+)/ do |what_to_say|
22
+ puts "#{@name} says '#{what_to_say.gsub(/_/, ' ')}'"
23
+ end
26
24
  end
27
25
 
28
26
  User.new('Ryan').say_hello_world # => Ryan says 'hello world'
29
27
 
30
28
  ## How It Works
31
29
 
32
- When you call the `rule` method in a class, it defines the constant `INSTANCE_RULEBOOK` and sets it to a new `RuleBook` instance; but only if the constant wasn't already defined. This way, it only defines the constant the first time you call the `rule` method.
33
-
34
- When the first time `rule` is called in a class, we also include the `RuleBook::IncludeMethods` module which overrides the classes `method_missing`. So when you call an undefined method on your class's instance, we will try to match the method against the rules you've defined in `INSTANCE_RULEBOOK`.
35
-
36
- There is also a method called `class_rule` which does the same as rules does, only it defines the `CLASS_RULEBOOK` constance in the class; which is a different `RuleBook` instance. The first time `class_rules` is called, it extends the class with the `RuleBook::ExtendMethods` module, which also contains a `method_missing` method.
30
+ TODO
37
31
 
38
32
  ## Better Example
39
33
 
40
34
  require 'rulebook'
41
35
 
42
36
  class User
43
- attr :name, :title
44
-
45
- def initialize(name)
46
- @name = name
47
- @title = :user
48
- end
49
-
50
- rule /is_(admin|moderator|super_user|user)/ do |title|
51
- @title = title.to_sym
52
- end
37
+ attr :name, :title
38
+
39
+ def initialize(name)
40
+ @name = name
41
+ @title = :user
42
+ end
43
+
44
+ rulebook.add /is_(admin|moderator|super_user|user)/ do |title|
45
+ @title = title.to_sym
46
+ end
53
47
  end
54
48
 
55
49
  You can now do things like
56
50
 
57
- users = [
58
- User.new('Ryan'),
59
- User.new('Natale'),
60
- User.new('Joe'),
61
- User.new('Monica'),
62
- User.new('Matt'),
63
- User.new('Jess')
64
- ].shuffle
51
+ users = ['Ryan', 'Natale', 'Kasey', 'Jenna', 'Joe', 'Monica','Allan', 'Amanda']
52
+ users.collect! { |n| User.new(n) }.shuffle!
65
53
 
66
54
  users[0].is_admin
67
55
  users[1].is_moderator
68
56
  users[2].is_super_user
69
57
 
70
58
  users.each do |user|
71
- puts "#{user.name} is a #{user.title}"
59
+ puts "#{user.name} is a #{user.title}"
72
60
  end
73
61
 
74
62
  ## Class Methods Example
@@ -76,26 +64,32 @@ You can now do things like
76
64
  require 'rulebook'
77
65
 
78
66
  class Car
79
- attr :make, :model
80
-
81
- def initialize(make, model)
82
- @make, @model = make.capitalize, model.capitalize
83
- end
84
-
85
- class_rule /new_([a-z]+)_(.+)/ do |make, model|
86
- new(make, model)
67
+ attr :make, :model
68
+
69
+ def initialize(make, model)
70
+ @make, @model = make.capitalize, model.capitalize
71
+ end
72
+
73
+ class << self
74
+ follows_the_rules!
75
+
76
+ rulebook.add /new_([a-z]+)_(.+)/ do |make, model|
77
+ new(make, model)
87
78
  end
79
+ end
88
80
  end
89
81
 
90
82
  my_cars = [
91
- Car.new_honda_accord,
92
- Car.new_dodge_neon,
93
- Car.new_volkswagen_beetle
83
+ Car.new_honda_accord,
84
+ Car.new_dodge_neon,
85
+ Car.new_volkswagen_beetle
94
86
  ]
95
87
 
96
88
  p my_cars.first.make # => "Honda"
97
89
  p my_cars.first.model # => "Accord"
98
90
 
91
+ This works out if you already have ``
92
+
99
93
  ### Now lets add some instance rules
100
94
 
101
95
  class Car
data/Rakefile CHANGED
@@ -1,64 +1,43 @@
1
1
  require 'rubygems'
2
- require 'rake'
3
2
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "rulebook"
8
- gem.summary = %Q{Allows you to define a set of 'rules' or dynamic methods to apply to a class}
9
- gem.description = %Q{Lets you define methods with regex for dynamic methods}
10
- gem.email = "c00lryguy@gmail.com"
11
- gem.homepage = "http://github.com/c00lryguy/rulebook"
12
- gem.authors = ["Ryan Lewis"]
13
- # gem.add_development_dependency "riot", ">= 0"
14
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
- end
16
- Jeweler::GemcutterTasks.new
17
- rescue LoadError
18
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
- end
3
+ # Gay as hell jeweler workaround
20
4
 
21
- require 'rake/testtask'
22
- Rake::TestTask.new(:test) do |test|
23
- test.libs << 'lib' << 'test'
24
- test.pattern = 'test/**/test_*.rb'
25
- test.verbose = false
26
- end
5
+ require 'psych'
6
+ YAML::ENGINE.yamler = 'psych'
27
7
 
8
+ require 'bundler'
28
9
  begin
29
- require 'rcov/rcovtask'
30
- Rcov::RcovTask.new do |test|
31
- test.libs << 'test'
32
- test.pattern = 'test/**/*_test.rb'
33
- test.verbose = false
34
- end
35
- rescue LoadError
36
- task :rcov do
37
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
- end
10
+ Bundler.setup(:default, :development)
11
+ rescue Bundler::BundlerError => e
12
+ $stderr.puts e.message
13
+ $stderr.puts "Run `bundle install` to install missing gems"
14
+ exit e.status_code
39
15
  end
16
+ require 'rake'
40
17
 
41
- task :test => :check_dependencies
42
-
43
- task :default => :test
44
-
45
- require 'rake/rdoctask'
46
- Rake::RDocTask.new do |rdoc|
47
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
-
49
- rdoc.rdoc_dir = 'rdoc'
50
- rdoc.title = "rulebook #{version}"
51
- rdoc.rdoc_files.include('README*')
52
- rdoc.rdoc_files.include('lib/**/*.rb')
18
+ require 'jeweler'
19
+ Jeweler::Tasks.new do |gem|
20
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
21
+ gem.name = "rulebook"
22
+ gem.homepage = "http://github.com/c00lryguy/rulebook"
23
+ gem.license = "MIT"
24
+ gem.summary = %Q{Define methods with regex for dynamic methods.}
25
+ gem.description = %Q{Allows you to define a set of 'rules' or dynamic methods to apply to a class.}
26
+ gem.email = "c00lryguy@gmail.com"
27
+ gem.authors = ["Ryan Lewis"]
28
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
29
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
30
+ gem.add_runtime_dependency 'meta_tools', '> 0.1'
31
+ gem.add_development_dependency 'rake', '> 0.0.0'
32
+ gem.add_development_dependency 'riot', '> 0.0.0'
53
33
  end
34
+ Jeweler::RubygemsDotOrgTasks.new
54
35
 
36
+ require 'rake/testtask'
55
37
 
56
- begin
57
- require 'reek/rake/task'
58
-
59
- Reek::Rake::Task.new do |t|
60
- t.fail_on_error = true
61
- t.verbose = true
62
- end
63
- rescue LoadError
64
- end
38
+ Rake::TestTask.new(:test) do |t|
39
+ t.libs.concat ['lib', 'test']
40
+ t.pattern = 'test/**/test_*.rb'
41
+ t.verbose = false
42
+ end
43
+ task :default => :test
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.3
1
+ 0.4.0
@@ -0,0 +1,43 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
+ require 'rulebook'
3
+
4
+ class User
5
+ follows_the_rules!
6
+
7
+ attr :title
8
+
9
+ def initialize(title=:user)
10
+ @title = title
11
+ end
12
+
13
+ rulebook.add /^is_(admin|user)$/ do |title|
14
+ @title = title.to_sym
15
+ self
16
+ end
17
+
18
+ rulebook.add /^is_(admin|user)\?$/ do |title|
19
+ @title == title.to_sym
20
+ end
21
+
22
+ class << self
23
+ metaclass.follows_the_rules!
24
+ metaclass.rulebook.add /^new_(admin|user)$/ do |title|
25
+ instance = new
26
+ instance.instance_eval { @title = title.to_sym }
27
+ instance
28
+ end
29
+ end
30
+ end
31
+
32
+ u = User.new
33
+
34
+ p u.is_user? # => true
35
+ p u.is_admin? # => false
36
+
37
+ u.is_admin
38
+
39
+ p u.is_user? # => false
40
+ p u.is_admin? # => true
41
+
42
+ u = User.new_admin
43
+ p u.is_admin? # => true
data/lib/rulebook.rb CHANGED
@@ -1,158 +1,19 @@
1
- class RuleBook
2
- class Rule
3
- attr :block
4
-
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)
7
- @what_to_capture, @block = what_to_capture, block
8
- end
9
-
10
- def [](query)
11
- query.to_s.match(@what_to_capture)
12
- end
13
- alias_method :match_against, :[]
14
-
15
- def matches_against?(query)
16
- !self[query].nil?
17
- end
18
- end
19
- end
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
20
2
 
21
- class RuleBook
22
- attr_accessor :rules
23
-
24
- def initialize
25
- @rules = []
26
- end
27
-
28
- def rule(what_to_capture, &block)
29
- rule = Rule.new(what_to_capture, &block)
30
- @rules << rule
31
- rule
32
- end
33
-
34
- def rules_that_match_against(regexp)
35
- @rules.find_all { |rule| rule.matches_against?(regexp) }
36
- end
3
+ class Rulebook
4
+ VERSION = "0.4.0"
37
5
  end
38
6
 
39
- # TODO: DRY up the code here a bit...
40
- class RuleBook
41
- module IncludeMethods
42
- def respond_to?(meth)
43
- rulebook = self.class.const_get('INSTANCE_RULEBOOK')
44
- rulebook.rules_that_match_against(meth).any? || super
45
- end
46
-
47
- def method_missing(meth, *args, &block)
48
- rulebook = self.class.const_get('INSTANCE_RULEBOOK')
49
- rules = rulebook.rules_that_match_against(meth)
50
-
51
- # TODO: Why would this ever be nil?
52
- unless rules.nil? || rules.empty?
53
- # Run the first matched rule..
54
- # TODO: if the method NEXT if called within the rule,
55
- # then goto the next matched rule
56
- rule = rules.first
57
- captures = rule[meth].captures || []
58
- block = rule.block
59
-
60
- # Remove the possibility of optional arguments
61
- arity = block.arity == -1 ? 0 : block.arity
62
-
63
- # Define the method
64
- klass = self.class
65
- klass.send(:define_method, meth) do |*args|
66
- instance_exec(*(captures + args).take(arity), &block)
67
- end
68
-
69
- # Call the method
70
- send(meth, *args, &block)
71
- else
72
- super
73
- end
74
- end
75
- end
76
-
77
- module ExtendMethods
78
- def respond_to?(meth)
79
- rulebook = const_get('CLASS_NOTEBOOK')
80
- rulebook.rules_that_match_against(meth).any? || super
81
- end
82
-
83
- def method_missing(meth, *args, &block)
84
- rulebook = const_get('CLASS_NOTEBOOK')
85
- rules = rulebook.rules_that_match_against(meth)
86
-
87
- # TODO: Why would this ever be nil?
88
- unless rules.nil? || rules.empty?
89
- # Run the first matched rule..
90
- # TODO: if the method NEXT if called within the rule,
91
- # then goto the next matched rule
92
- rule = rules.first
93
- captures = rule[meth].captures || []
94
- block = rule.block
95
-
96
- # Remove the possibility of optional arguments
97
- arity = block.arity == -1 ? 0 : block.arity
98
-
99
- # Define the method
100
- klass = class << self; self; end
101
- klass.send(:define_method, meth) do |*args|
102
- class_exec(*(captures + args).take(arity), &block)
103
- end
104
-
105
- # Call the method
106
- send(meth, *args, &block)
107
- else
108
- super
109
- end
110
- end
111
- end
112
- end
7
+ require 'rulebook/rule'
113
8
 
114
- # TODO: DRY up the code here too...
115
- class Module
116
- def rule(what_to_capture, &block)
117
- raise(ArgumentError, 'rules must have a block') unless block_given?
118
-
119
- setup_rulebook('INSTANCE_RULEBOOK', :include)
120
- const_get('INSTANCE_RULEBOOK').rule(what_to_capture, &block)
121
- end
122
-
123
- def class_rule(what_to_capture, &block)
124
- raise(ArgumentError, 'class_rules must have a block') unless block_given?
125
-
126
- setup_rulebook('CLASS_NOTEBOOK', :extend)
127
- const_get('CLASS_NOTEBOOK').rule(what_to_capture, &block)
128
- end
129
-
130
- def rules(&block)
131
- raise(ArgumentError, 'rules must have a block') unless block_given?
132
-
133
- setup_rulebook('INSTANCE_RULEBOOK', :include)
134
- const_get('INSTANCE_RULEBOOK').instance_eval(&block)
135
- const_get('INSTANCE_RULEBOOK')
136
- end
137
-
138
- def class_rules(&block)
139
- raise(ArgumentError, 'class_rules must have a block') unless block_given?
140
-
141
- setup_rulebook('CLASS_NOTEBOOK', :extend)
142
- const_get('CLASS_NOTEBOOK').instance_eval(&block)
143
- const_get('CLASS_NOTEBOOK')
144
- end
145
-
146
- private
147
-
148
- def setup_rulebook(rulebook_constant, extend_or_include)
149
- raise(ArgumentError, 'extend_or_include must be :extend or :include') unless [:extend, :include].include?(extend_or_include)
150
-
151
- unless const_defined?(rulebook_constant)
152
- const_set(rulebook_constant, RuleBook.new)
153
-
154
- module_name = extend_or_include.to_s.capitalize + 'Methods'
155
- send(extend_or_include, RuleBook.const_get(module_name))
156
- end
157
- end
9
+ class Rulebook
10
+ attr_accessor :rules
11
+ def initialize; @rules = []; end
12
+ def add(what_to_capture, &block); @rules << Rule.new(what_to_capture, &block); end
13
+ def [](query); @rules.find_all { |rule| rule.matches_against?(query) }; end
14
+ alias_method :rules_that_match_against, :[]
158
15
  end
16
+
17
+ require 'rulebook/class_methods'
18
+ require 'rulebook/instance_methods'
19
+ require 'rulebook/core_ext/module'