rulebook 0.3.3 → 0.4.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/.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'