rulebook 0.4.3 → 0.5.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/Gemfile.lock +18 -8
- data/LICENSE +1 -1
- data/Rakefile +3 -8
- data/VERSION +1 -1
- data/examples/simple.rb +56 -54
- data/lib/core_ext.rb +82 -0
- data/lib/rulebook.rb +40 -13
- data/rulebook.gemspec +53 -51
- data/spec/module_class_methods_spec.rb +17 -0
- data/spec/rule_spec.rb +6 -0
- data/spec/rulebook_spec.rb +38 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/user.rb +18 -0
- data/spec/user_spec.rb +65 -0
- metadata +49 -26
- data/lib/rulebook/class_methods.rb +0 -6
- data/lib/rulebook/core_ext/module.rb +0 -24
- data/lib/rulebook/instance_methods.rb +0 -41
- data/lib/rulebook/rule.rb +0 -18
- data/test/helper.rb +0 -7
- data/test/test_chevy.rb +0 -56
- data/test/test_rule.rb +0 -10
data/Gemfile.lock
CHANGED
@@ -1,23 +1,33 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rulebook (0.
|
5
|
-
meta_tools (
|
4
|
+
rulebook (0.5.0)
|
5
|
+
meta_tools (~> 0.2.3)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
|
10
|
+
diff-lcs (1.1.3)
|
11
|
+
meta_tools (0.2.5)
|
12
|
+
mocha (0.9.12)
|
11
13
|
rake (0.9.2)
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
rspec (2.6.0)
|
15
|
+
rspec-core (~> 2.6.0)
|
16
|
+
rspec-expectations (~> 2.6.0)
|
17
|
+
rspec-mocks (~> 2.6.0)
|
18
|
+
rspec-core (2.6.4)
|
19
|
+
rspec-expectations (2.6.0)
|
20
|
+
diff-lcs (~> 1.1.2)
|
21
|
+
rspec-mocks (2.6.0)
|
22
|
+
shoulda (2.11.3)
|
15
23
|
|
16
24
|
PLATFORMS
|
17
25
|
ruby
|
18
26
|
x86-mingw32
|
19
27
|
|
20
28
|
DEPENDENCIES
|
21
|
-
|
22
|
-
|
29
|
+
mocha (~> 0.9.12)
|
30
|
+
rake (~> 0.9.2)
|
31
|
+
rspec (~> 2.6.0)
|
23
32
|
rulebook!
|
33
|
+
shoulda (~> 2.11.3)
|
data/LICENSE
CHANGED
data/Rakefile
CHANGED
@@ -10,11 +10,6 @@ rescue Bundler::BundlerError => e
|
|
10
10
|
end
|
11
11
|
require 'rake'
|
12
12
|
|
13
|
-
require '
|
14
|
-
|
15
|
-
|
16
|
-
t.libs.concat ['lib', 'test']
|
17
|
-
t.pattern = 'test/**/test_*.rb'
|
18
|
-
t.verbose = false
|
19
|
-
end
|
20
|
-
task :default => :test
|
13
|
+
require 'rspec/core/rake_task'
|
14
|
+
RSpec::Core::RakeTask.new(:spec)
|
15
|
+
task :default => :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/examples/simple.rb
CHANGED
@@ -1,54 +1,56 @@
|
|
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
|
-
follows_the_rules!
|
24
|
-
|
25
|
-
|
26
|
-
instance
|
27
|
-
instance
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
p u.
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
p u.
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
+
follows_the_rules!
|
24
|
+
|
25
|
+
rulebook.add /^new_(admin|user)$/ do |title|
|
26
|
+
instance = new
|
27
|
+
instance.instance_eval { @title = title.to_sym }
|
28
|
+
instance
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
u = User.new
|
34
|
+
|
35
|
+
p u.is_user? # => true
|
36
|
+
p u.is_admin? # => false
|
37
|
+
|
38
|
+
u.is_admin
|
39
|
+
|
40
|
+
p u.is_user? # => false
|
41
|
+
p u.is_admin? # => true
|
42
|
+
|
43
|
+
u = User.new_admin
|
44
|
+
p u
|
45
|
+
p u.is_admin? # => true
|
46
|
+
|
47
|
+
|
48
|
+
# DEV: TODO CLASS RULES O_O
|
49
|
+
Integer.follows_the_rules!
|
50
|
+
Integer.rulebook.add /to_base_(\d+)/ do |base|
|
51
|
+
p base
|
52
|
+
p "OMG"
|
53
|
+
to_s(base)
|
54
|
+
end
|
55
|
+
|
56
|
+
p 10.to_base_16
|
data/lib/core_ext.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
class Module
|
2
|
+
# This declares that the current class has a rulebook
|
3
|
+
# with rules that it wants it's instances to follow.
|
4
|
+
#
|
5
|
+
# I picked this name because the probability of someone needing the method
|
6
|
+
# 'follows_the_rules!' (with a bang) is slim... hopefully.
|
7
|
+
def follows_the_rules!
|
8
|
+
extend(MetaTools)
|
9
|
+
include(MetaTools)
|
10
|
+
|
11
|
+
meta_def(:def_class_rule) do |what_to_capture, &class_block|
|
12
|
+
|
13
|
+
class_eval { @rulebook ||= Rulebook.new }.add(what_to_capture, &class_block)
|
14
|
+
|
15
|
+
# unless respond_to?(:method_missing)
|
16
|
+
meta_def(:method_missing) do |meth, *args, &block|
|
17
|
+
|
18
|
+
matching_rules = @rulebook[meth]
|
19
|
+
|
20
|
+
unless matching_rules.empty?
|
21
|
+
rule = matching_rules.first
|
22
|
+
rule_block = rule.block
|
23
|
+
rule_captures = rule[meth].captures || []
|
24
|
+
#rule_arity = rule_block.arity == -1 ? 0 : rule_block.arity
|
25
|
+
# The above removes the possibility of optional arguments
|
26
|
+
|
27
|
+
# Define the method
|
28
|
+
unless meta_class.respond_to?(meth)
|
29
|
+
meta_def(meth) do |*rule_args|
|
30
|
+
rule_args = (rule_captures + rule_args)#.take(rule_arity)
|
31
|
+
instance_exec(*rule_args, &rule_block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
send(meth, *args, &block)
|
36
|
+
else
|
37
|
+
super(meth, *args, &block)
|
38
|
+
end # matching_rules.empty?
|
39
|
+
|
40
|
+
end # meta_def(:method_missing)
|
41
|
+
|
42
|
+
# end # respond_to?(:method_missing)
|
43
|
+
|
44
|
+
end # def_class_rule
|
45
|
+
|
46
|
+
meta_def(:def_rule) do |what_to_capture, &class_block|
|
47
|
+
|
48
|
+
(@rulebook ||= Rulebook.new).add(what_to_capture, &class_block)
|
49
|
+
|
50
|
+
# unless respond_to?(:method_missing)
|
51
|
+
define_method(:method_missing) do |meth, *args, &block|
|
52
|
+
matching_rules = self.class.instance_variable_get(:@rulebook)[meth]
|
53
|
+
|
54
|
+
unless matching_rules.empty?
|
55
|
+
rule = matching_rules.first
|
56
|
+
rule_block = rule.block
|
57
|
+
rule_captures = rule[meth].captures || []
|
58
|
+
# rule_arity = rule_block.arity == -1 ? 0 : rule_block.arity
|
59
|
+
# The above removes the possibility of optional arguments
|
60
|
+
|
61
|
+
# Define the method
|
62
|
+
unless meta_class.respond_to?(meth)
|
63
|
+
meta_def(meth) do |*rule_args|
|
64
|
+
rule_args = (rule_captures + rule_args)#.take(rule_arity)
|
65
|
+
instance_exec(*rule_args, &rule_block)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
send(meth, *args, &block)
|
70
|
+
else
|
71
|
+
super(meth, *args, &block)
|
72
|
+
end # matching_rules.empty?
|
73
|
+
|
74
|
+
end # meta_def(:method_missing)
|
75
|
+
|
76
|
+
# end # respond_to?(:method_missing)
|
77
|
+
|
78
|
+
end # def_rule
|
79
|
+
|
80
|
+
end # follows_the_rules!
|
81
|
+
|
82
|
+
end # Module
|
data/lib/rulebook.rb
CHANGED
@@ -1,19 +1,46 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Rulebook
|
4
|
-
VERSION = "0.4.3"
|
5
|
-
end
|
6
|
-
|
7
|
-
require 'rulebook/rule'
|
1
|
+
__DIR__ = File.dirname(__FILE__)
|
2
|
+
$:.unshift(__DIR__) unless $:.include?(__DIR__)
|
8
3
|
|
9
4
|
class Rulebook
|
5
|
+
VERSION = "0.5.0"
|
6
|
+
|
7
|
+
class Rule
|
8
|
+
attr :block
|
9
|
+
|
10
|
+
def initialize(regexp, &block)
|
11
|
+
# TODO: Match more than Regexp. Strings and Symbols pls.
|
12
|
+
raise(TypeError, 'regexp must be of type Regexp') unless regexp.is_a?(Regexp)
|
13
|
+
raise(ArgumentError, 'a block is needed') unless block_given?
|
14
|
+
@regexp, @block = regexp, block
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](query)
|
18
|
+
query.to_s.downcase.match(@regexp)
|
19
|
+
end
|
20
|
+
alias_method :match, :[]
|
21
|
+
|
22
|
+
def matches?(query)
|
23
|
+
!self[query].nil?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
10
27
|
attr_accessor :rules
|
11
|
-
|
12
|
-
def
|
13
|
-
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@rules = []
|
31
|
+
end
|
32
|
+
|
33
|
+
def add(regexp, &block)
|
34
|
+
@rules << Rule.new(regexp, &block)
|
35
|
+
end
|
36
|
+
# alias_method :<<. :add
|
37
|
+
|
38
|
+
def [](query)
|
39
|
+
@rules.find_all { |rule| rule.matches?(query) }
|
40
|
+
end
|
14
41
|
alias_method :rules_that_match_against, :[]
|
42
|
+
alias_method :match, :[]
|
15
43
|
end
|
16
44
|
|
17
|
-
require '
|
18
|
-
require '
|
19
|
-
require 'rulebook/core_ext/module'
|
45
|
+
require 'meta_tools'
|
46
|
+
require 'core_ext'
|
data/rulebook.gemspec
CHANGED
@@ -1,52 +1,54 @@
|
|
1
|
-
Gem::Specification.new do |s|
|
2
|
-
s.author = "Ryan Scott Lewis"
|
3
|
-
s.email = "c00lryguy@gmail.com"
|
4
|
-
s.homepage = "http://github.com/c00lryguy/rulebook"
|
5
|
-
|
6
|
-
s.description = "Allows you to define a set of 'rules' or dynamic methods to apply to a class."
|
7
|
-
s.summary = "Define methods with regex for dynamic methods."
|
8
|
-
|
9
|
-
s.require_paths = ["lib"]
|
10
|
-
|
11
|
-
s.name = File.basename(__FILE__, ".gemspec")
|
12
|
-
s.version = File.read("VERSION")
|
13
|
-
# VERSIONING
|
14
|
-
# Some people like to use a YAML file to display the version, some like CSV,
|
15
|
-
# others might just add a constant set to a version string, some (Rack) might
|
16
|
-
# even have an array splitting the version into parts.
|
17
|
-
# Just edit the above line appropriately.
|
18
|
-
# An easy thing to do is set a constant within your app to a version string
|
19
|
-
# and use it in here
|
20
|
-
|
21
|
-
# Add directories you *might* use in ALL projects.
|
22
|
-
s.files = [File.basename(__FILE__)] + Dir['lib/**/*'] + Dir['bin/**/*'] + Dir['test/**/*'] + Dir['examples/**/*']
|
23
|
-
|
24
|
-
# Add files you *might* use in ALL projects!
|
25
|
-
%W{Gemfile.lock README.* README Rakefile VERSION LICENSE}.each do |file|
|
26
|
-
s.files.unshift(file) if File.exists?(file)
|
27
|
-
end
|
28
|
-
|
29
|
-
# Add files you *might* use in ALL projects!
|
30
|
-
%W{README.* README VERSION LICENSE LICENSE.*}.each do |file|
|
31
|
-
(s.extra_rdoc_files ||= []).unshift(file) if File.exists?(file)
|
32
|
-
end
|
33
|
-
|
34
|
-
# s.executables = ["bin/myapp.rb"]
|
35
|
-
|
36
|
-
# If you only specify one application file in executables, that file becomes
|
37
|
-
# the default executable. Therefore, you only need to specify this value if you
|
38
|
-
# have more than one application file.
|
39
|
-
if s.executables.length > 1
|
40
|
-
if exe = s.executables.find { |e| e.include?(File.basename(__FILE__, ".gemspec")) }
|
41
|
-
s.default_executable = exe
|
42
|
-
else
|
43
|
-
raise(Exception, "Couldn't automatically figure out the default_executable")
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
s.test_files = Dir['test/**/*'] + Dir['examples/**/*']
|
48
|
-
|
49
|
-
s.add_dependency("meta_tools", "0.2.3")
|
50
|
-
s.add_development_dependency("rake", "0.9.2")
|
51
|
-
s.add_development_dependency("
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.author = "Ryan Scott Lewis"
|
3
|
+
s.email = "c00lryguy@gmail.com"
|
4
|
+
s.homepage = "http://github.com/c00lryguy/rulebook"
|
5
|
+
|
6
|
+
s.description = "Allows you to define a set of 'rules' or dynamic methods to apply to a class."
|
7
|
+
s.summary = "Define methods with regex for dynamic methods."
|
8
|
+
|
9
|
+
s.require_paths = ["lib"]
|
10
|
+
|
11
|
+
s.name = File.basename(__FILE__, ".gemspec")
|
12
|
+
s.version = File.read("VERSION")
|
13
|
+
# VERSIONING
|
14
|
+
# Some people like to use a YAML file to display the version, some like CSV,
|
15
|
+
# others might just add a constant set to a version string, some (Rack) might
|
16
|
+
# even have an array splitting the version into parts.
|
17
|
+
# Just edit the above line appropriately.
|
18
|
+
# An easy thing to do is set a constant within your app to a version string
|
19
|
+
# and use it in here
|
20
|
+
|
21
|
+
# Add directories you *might* use in ALL projects.
|
22
|
+
s.files = [File.basename(__FILE__)] + Dir['lib/**/*'] + Dir['bin/**/*'] + Dir['test/**/*'] + Dir['examples/**/*'] + Dir['spec/**/*']
|
23
|
+
|
24
|
+
# Add files you *might* use in ALL projects!
|
25
|
+
%W{Gemfile.lock README.* README Rakefile VERSION LICENSE}.each do |file|
|
26
|
+
s.files.unshift(file) if File.exists?(file)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Add files you *might* use in ALL projects!
|
30
|
+
%W{README.* README VERSION LICENSE LICENSE.*}.each do |file|
|
31
|
+
(s.extra_rdoc_files ||= []).unshift(file) if File.exists?(file)
|
32
|
+
end
|
33
|
+
|
34
|
+
# s.executables = ["bin/myapp.rb"]
|
35
|
+
|
36
|
+
# If you only specify one application file in executables, that file becomes
|
37
|
+
# the default executable. Therefore, you only need to specify this value if you
|
38
|
+
# have more than one application file.
|
39
|
+
if s.executables.length > 1
|
40
|
+
if exe = s.executables.find { |e| e.include?(File.basename(__FILE__, ".gemspec")) }
|
41
|
+
s.default_executable = exe
|
42
|
+
else
|
43
|
+
raise(Exception, "Couldn't automatically figure out the default_executable")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
s.test_files = Dir['test/**/*'] + Dir['examples/**/*'] + Dir['spec/**/*']
|
48
|
+
|
49
|
+
s.add_dependency("meta_tools", "~> 0.2.3")
|
50
|
+
s.add_development_dependency("rake", "~> 0.9.2")
|
51
|
+
s.add_development_dependency("rspec", "~> 2.6.0")
|
52
|
+
s.add_development_dependency("shoulda", "~> 2.11.3")
|
53
|
+
s.add_development_dependency("mocha", "~> 0.9.12")
|
52
54
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SomeService
|
4
|
+
follows_the_rules!
|
5
|
+
|
6
|
+
def_class_rule(/^say_([a-z_]+)$/) do |message|
|
7
|
+
message.gsub(/_/, ' ')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe SomeService do
|
12
|
+
describe "When a method matches the rule's regexp" do
|
13
|
+
it "should respond correctly" do
|
14
|
+
SomeService.say_hello_world.should == "hello world"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/rule_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rulebook do
|
4
|
+
let(:rulebook) { Rulebook.new }
|
5
|
+
let(:regexp) { /^foobar$/ }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
it "should have the #rules method available" do
|
9
|
+
rulebook.should be_instance_of(Rulebook)
|
10
|
+
rulebook.should respond_to(:rules)
|
11
|
+
rulebook.rules.should == Array.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#add and #<<" do
|
16
|
+
it "should add a rule correctly" do
|
17
|
+
block = proc { puts "Foobar" }
|
18
|
+
|
19
|
+
Rulebook::Rule.expects(:initialize).with(regexp, block)
|
20
|
+
|
21
|
+
rulebook.rules.length.should == 0
|
22
|
+
rulebook.add(regexp, &block)
|
23
|
+
rulebook.rules.length.should == 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#[], #match, and #rules_that_match_against" do
|
28
|
+
it "should return an Array of rules that match the given query" do
|
29
|
+
query = "foobar"
|
30
|
+
|
31
|
+
rulebook.add(regexp) { "Foobar" }
|
32
|
+
|
33
|
+
rulebook[query].should == [rulebook.rules.first]
|
34
|
+
rulebook.match(query).should == [rulebook.rules.first]
|
35
|
+
rulebook.rules_that_match_against(query).should == [rulebook.rules.first]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class User
|
2
|
+
follows_the_rules!
|
3
|
+
|
4
|
+
attr :role
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@role = :user
|
8
|
+
end
|
9
|
+
|
10
|
+
def_class_rule(/new_(admin|moderator|user)/) do |role|
|
11
|
+
new.instance_eval { @role = role.to_sym; self }
|
12
|
+
end
|
13
|
+
|
14
|
+
def_rule(/is_(admin|moderator|user)\?/) do |role|
|
15
|
+
@role == role.to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/spec/user_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe User do
|
4
|
+
describe ".new" do
|
5
|
+
it "returns a new User with the role of :user" do
|
6
|
+
User.new.instance_variable_get(:@role).should == :user
|
7
|
+
end
|
8
|
+
end
|
9
|
+
describe ".new_user" do
|
10
|
+
it "returns a new User with the role of :user" do
|
11
|
+
User.new_user.instance_variable_get(:@role).should == :user
|
12
|
+
end
|
13
|
+
end
|
14
|
+
describe ".new_moderator" do
|
15
|
+
it "returns a new User with the role of :moderator" do
|
16
|
+
User.new_moderator.instance_variable_get(:@role).should == :moderator
|
17
|
+
end
|
18
|
+
end
|
19
|
+
describe ".new_admin" do
|
20
|
+
it "returns a new User with the role of :admin" do
|
21
|
+
User.new_admin.instance_variable_get(:@role).should == :admin
|
22
|
+
end
|
23
|
+
end
|
24
|
+
describe "#is_user?" do
|
25
|
+
describe "when the user's role is :user" do
|
26
|
+
it "should return true" do
|
27
|
+
User.new.is_user?.should == true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
describe "when the user's role is not :user" do
|
31
|
+
it "should return false" do
|
32
|
+
User.new_moderator.is_user?.should == false
|
33
|
+
User.new_admin.is_user?.should == false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
describe "#is_moderator?" do
|
38
|
+
describe "when the user's role is :moderator" do
|
39
|
+
it "should return true" do
|
40
|
+
User.new_moderator.is_moderator?.should == true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
describe "when the user's role is not :moderator" do
|
44
|
+
it "should return false" do
|
45
|
+
User.new.is_moderator?.should == false
|
46
|
+
User.new_user.is_moderator?.should == false
|
47
|
+
User.new_admin.is_moderator?.should == false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
describe "#is_admin?" do
|
52
|
+
describe "when the user's role is :admin" do
|
53
|
+
it "should return true" do
|
54
|
+
User.new_admin.is_admin?.should == true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
describe "when the user's role is not :admin" do
|
58
|
+
it "should return false" do
|
59
|
+
User.new.is_admin?.should == false
|
60
|
+
User.new_user.is_admin?.should == false
|
61
|
+
User.new_moderator.is_admin?.should == false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rulebook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,42 +9,63 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
13
|
-
default_executable:
|
12
|
+
date: 2011-09-05 00:00:00.000000000Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: meta_tools
|
17
|
-
requirement: &
|
16
|
+
requirement: &70328089193000 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
|
-
- -
|
19
|
+
- - ~>
|
21
20
|
- !ruby/object:Gem::Version
|
22
21
|
version: 0.2.3
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
24
|
+
version_requirements: *70328089193000
|
26
25
|
- !ruby/object:Gem::Dependency
|
27
26
|
name: rake
|
28
|
-
requirement: &
|
27
|
+
requirement: &70328089192520 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
29
|
requirements:
|
31
|
-
- -
|
30
|
+
- - ~>
|
32
31
|
- !ruby/object:Gem::Version
|
33
32
|
version: 0.9.2
|
34
33
|
type: :development
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
35
|
+
version_requirements: *70328089192520
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
39
|
-
requirement: &
|
37
|
+
name: rspec
|
38
|
+
requirement: &70328089192060 !ruby/object:Gem::Requirement
|
40
39
|
none: false
|
41
40
|
requirements:
|
42
|
-
- -
|
41
|
+
- - ~>
|
43
42
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
43
|
+
version: 2.6.0
|
45
44
|
type: :development
|
46
45
|
prerelease: false
|
47
|
-
version_requirements: *
|
46
|
+
version_requirements: *70328089192060
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: shoulda
|
49
|
+
requirement: &70328089191600 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.11.3
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70328089191600
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: mocha
|
60
|
+
requirement: &70328089191140 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.9.12
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70328089191140
|
48
69
|
description: Allows you to define a set of 'rules' or dynamic methods to apply to
|
49
70
|
a class.
|
50
71
|
email: c00lryguy@gmail.com
|
@@ -59,16 +80,15 @@ files:
|
|
59
80
|
- Rakefile
|
60
81
|
- Gemfile.lock
|
61
82
|
- rulebook.gemspec
|
62
|
-
- lib/
|
63
|
-
- lib/rulebook/core_ext/module.rb
|
64
|
-
- lib/rulebook/instance_methods.rb
|
65
|
-
- lib/rulebook/rule.rb
|
83
|
+
- lib/core_ext.rb
|
66
84
|
- lib/rulebook.rb
|
67
|
-
- test/helper.rb
|
68
|
-
- test/test_chevy.rb
|
69
|
-
- test/test_rule.rb
|
70
85
|
- examples/simple.rb
|
71
|
-
|
86
|
+
- spec/module_class_methods_spec.rb
|
87
|
+
- spec/rule_spec.rb
|
88
|
+
- spec/rulebook_spec.rb
|
89
|
+
- spec/spec_helper.rb
|
90
|
+
- spec/support/user.rb
|
91
|
+
- spec/user_spec.rb
|
72
92
|
homepage: http://github.com/c00lryguy/rulebook
|
73
93
|
licenses: []
|
74
94
|
post_install_message:
|
@@ -89,12 +109,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
109
|
version: '0'
|
90
110
|
requirements: []
|
91
111
|
rubyforge_project:
|
92
|
-
rubygems_version: 1.6
|
112
|
+
rubygems_version: 1.8.6
|
93
113
|
signing_key:
|
94
114
|
specification_version: 3
|
95
115
|
summary: Define methods with regex for dynamic methods.
|
96
116
|
test_files:
|
97
|
-
- test/helper.rb
|
98
|
-
- test/test_chevy.rb
|
99
|
-
- test/test_rule.rb
|
100
117
|
- examples/simple.rb
|
118
|
+
- spec/module_class_methods_spec.rb
|
119
|
+
- spec/rule_spec.rb
|
120
|
+
- spec/rulebook_spec.rb
|
121
|
+
- spec/spec_helper.rb
|
122
|
+
- spec/support/user.rb
|
123
|
+
- spec/user_spec.rb
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'meta_tools'
|
2
|
-
|
3
|
-
#++
|
4
|
-
# Should this be class Object?
|
5
|
-
# Is there really a difference?
|
6
|
-
#--
|
7
|
-
class Module
|
8
|
-
# This declares that the current class has a rulebook
|
9
|
-
# with rules that it wants it's instances to follow.
|
10
|
-
#
|
11
|
-
# I picked this name because the probability of someone needing the method
|
12
|
-
# 'follows_the_rules!' (with a bang) is slim... hopefully.
|
13
|
-
#
|
14
|
-
# This adds the following method:
|
15
|
-
# User#rulebook
|
16
|
-
# Returns the RuleBook instance that contains the defined rules.
|
17
|
-
def follows_the_rules!
|
18
|
-
extend(MetaTools)
|
19
|
-
include(MetaTools)
|
20
|
-
|
21
|
-
extend(Rulebook::ClassMethods)
|
22
|
-
include(Rulebook::InstanceMethods)
|
23
|
-
end
|
24
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
class Rulebook
|
2
|
-
module InstanceMethods
|
3
|
-
def method_missing(meth, *args, &blk)
|
4
|
-
# Classes and instances find their rulebook differently.
|
5
|
-
begin
|
6
|
-
rulebook = self.class.rulebook
|
7
|
-
rescue NoMethodError
|
8
|
-
rulebook = metaclass.rulebook
|
9
|
-
end
|
10
|
-
|
11
|
-
rules = rulebook.rules_that_match_against(meth)
|
12
|
-
unless rules.nil?
|
13
|
-
rules.each do |rule|
|
14
|
-
# =S Run all matched rules or run first matched rule...?
|
15
|
-
# rule = rules.first
|
16
|
-
|
17
|
-
captures = rule[meth].captures || []
|
18
|
-
block = rule.block
|
19
|
-
|
20
|
-
# Remove the possibility of optional arguments
|
21
|
-
arity = block.arity == -1 ? 0 : block.arity
|
22
|
-
|
23
|
-
# Define the method
|
24
|
-
meta_def(meth) do |*args|
|
25
|
-
instance_exec(*(captures + args).take(arity), &block)
|
26
|
-
end
|
27
|
-
|
28
|
-
# klass = self.class
|
29
|
-
# klass.send(:define_method, meth) do |*args|
|
30
|
-
# instance_exec(*(captures + args).take(arity), &block)
|
31
|
-
# end
|
32
|
-
|
33
|
-
# Call the method and return the result
|
34
|
-
return send(meth, *args, &block)
|
35
|
-
end
|
36
|
-
else
|
37
|
-
super
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/rulebook/rule.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
class Rulebook
|
2
|
-
# This class creates an instance of a Rule, which holds the
|
3
|
-
# Regexp to match against and the block to run when matched
|
4
|
-
class Rule
|
5
|
-
attr :block
|
6
|
-
|
7
|
-
def initialize(what_to_capture, &block)
|
8
|
-
# TODO: Match more than Regexp. Strings and Symbols pls.
|
9
|
-
raise(TypeError, 'what_to_capture must be of type Regexp') unless what_to_capture.is_a?(Regexp)
|
10
|
-
raise(ArgumentError, 'a block is needed') unless block_given?
|
11
|
-
@what_to_capture, @block = what_to_capture, block
|
12
|
-
end
|
13
|
-
|
14
|
-
def [](query); query.to_s.downcase.match(@what_to_capture); end
|
15
|
-
alias_method :match_against, :[]
|
16
|
-
def matches_against?(query); !self[query].nil?; end
|
17
|
-
end
|
18
|
-
end
|
data/test/helper.rb
DELETED
data/test/test_chevy.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class Engine
|
4
|
-
follows_the_rules!
|
5
|
-
|
6
|
-
attr_accessor :state
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@state = :off
|
10
|
-
end
|
11
|
-
|
12
|
-
rulebook.add(/is_(off|idle|broken)/) do |state|
|
13
|
-
@state = state.to_sym
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
rulebook.add(/is_(off|idle|broken)\?/) do |state|
|
18
|
-
@state == state.to_sym
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context "A Chevy engine" do
|
23
|
-
setup { Engine.new }
|
24
|
-
|
25
|
-
context "that is off" do
|
26
|
-
asserts_topic.assigns(:state, :off)
|
27
|
-
asserts(:state).equals(:off)
|
28
|
-
end
|
29
|
-
|
30
|
-
context "that is idle" do
|
31
|
-
setup { topic.is_idle }
|
32
|
-
asserts_topic.assigns(:state, :idle)
|
33
|
-
asserts(:state).equals(:idle)
|
34
|
-
end
|
35
|
-
|
36
|
-
context "that is broken as usual" do
|
37
|
-
setup { topic.is_broken }
|
38
|
-
asserts_topic.assigns(:state, :broken)
|
39
|
-
end
|
40
|
-
|
41
|
-
context "checked with custom rule" do
|
42
|
-
context "that is off" do
|
43
|
-
asserts(:is_off?)
|
44
|
-
end
|
45
|
-
|
46
|
-
context "that is idle" do
|
47
|
-
setup { topic.is_idle }
|
48
|
-
asserts(:is_idle?)
|
49
|
-
end
|
50
|
-
|
51
|
-
context "that is broken as usual" do
|
52
|
-
setup { topic.is_broken }
|
53
|
-
asserts(:is_broken?)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
data/test/test_rule.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
context "A rule all on it's lonesome" do
|
4
|
-
setup do
|
5
|
-
Rulebook::Rule.new(/is_lonely/) { "='(" }
|
6
|
-
end
|
7
|
-
asserts("that this rule truly is alone") { topic.matches_against?(:is_lonely) }
|
8
|
-
denies("an awkward method") { topic.matches_against?(:is_surrounded_by_other_rule_friends) }
|
9
|
-
asserts("this works with Strings") { topic.matches_against?("is_lonely") }
|
10
|
-
end
|