rulebook 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|