matches 1.0.3 → 1.0.4

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/TODO.md ADDED
@@ -0,0 +1,10 @@
1
+ To do
2
+ =====
3
+
4
+ Implement regular-expression priorities like Cucumber:
5
+ ------------------------------------------------------
6
+
7
+ 1. The longest Regexp with 0 capture groups always wins.
8
+ 2. The Regexp with the most capture groups wins (when there are none with 0 groups)
9
+ 3. If there are 2+ Regexen with the same number of capture groups, the one with the shortest overall captured string length wins
10
+ 4. If there are still 2+ options then an Ambiguous error is raised
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.3
1
+ 1.0.4
@@ -6,7 +6,7 @@ Scenario: Define a matcher method
6
6
  Given I have the following Ruby code:
7
7
  """
8
8
  class Hippo
9
- matches /(\w+)\!/ do |verb|
9
+ matches /^(\w+)\!$/ do |verb|
10
10
  puts "I've been #{verb}ed!"
11
11
  end
12
12
  end
@@ -17,7 +17,6 @@ Scenario: Define a matcher method
17
17
  Then I should see "I've been touched!" in the output
18
18
 
19
19
  Scenario: Another meta-method
20
- Given I reset the class Hippo
21
20
  Given I have the following Ruby code:
22
21
  """
23
22
  class Hippo
@@ -25,11 +24,11 @@ Scenario: Another meta-method
25
24
  @verbs = []
26
25
  end
27
26
 
28
- matches /(\w+)\!/ do |verb|
27
+ matches /^(\w+)\!$/ do |verb|
29
28
  @verbs << verb
30
29
  end
31
30
 
32
- matches /(\w+)ed\?/ do |verb|
31
+ matches /^(\w+)ed\?$/ do |verb|
33
32
  @verbs.include?(verb)
34
33
  end
35
34
  end
@@ -41,4 +40,29 @@ Scenario: Another meta-method
41
40
  puts herman.touched?
42
41
  """
43
42
  When I execute the code
44
- Then I should see "true" in the output
43
+ Then I should see "true" in the output
44
+
45
+ Scenario: Defining class methods
46
+ Given I have the following Ruby code:
47
+ """
48
+ class Hippo
49
+ attr_accessor :disposition
50
+
51
+ def initialize(dis)
52
+ self.disposition = dis
53
+ end
54
+
55
+ class << self
56
+ matches /^new_(\w+)$/ do |dis|
57
+ new(dis)
58
+ end
59
+ end
60
+ end
61
+
62
+ herman = Hippo.new_angry
63
+
64
+ puts herman.disposition
65
+ """
66
+ When I execute the code
67
+ Then I should see "angry" in the output
68
+
@@ -1,7 +1,3 @@
1
- Given /^I reset the class (.+)$/ do |klass|
2
- eval("#{klass}.reset_meta_methods")
3
- end
4
-
5
1
  Given /^I have the following Ruby code:$/ do |code|
6
2
  @code = code
7
3
  end
@@ -30,4 +26,8 @@ class OutputStorage
30
26
  def self.output
31
27
  @@output
32
28
  end
29
+
30
+ def self.clear
31
+ @@output = ""
32
+ end
33
33
  end
@@ -1,3 +1,16 @@
1
1
  require File.dirname(__FILE__) + "/../../lib/matches"
2
2
 
3
- require 'spec/stubs/cucumber'
3
+ require 'spec/stubs/cucumber'
4
+
5
+ Before do
6
+ # Look through all the classes, some of which will have been defined
7
+ # in the scenarios. Reset their match methods if necessary.
8
+ Module.constants.each do |constant|
9
+ klass = Kernel.const_get(constant)
10
+ if klass.kind_of?(Class)
11
+ klass.reset_match_methods if klass.respond_to?(:reset_match_methods)
12
+ end
13
+ end
14
+
15
+ OutputStorage.clear()
16
+ end
data/lib/matches.rb CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + "/match_method"
2
2
 
3
3
  # Defines all the necessary components to allow defining dynamic methods.
4
4
  module MatchDef
5
- # Defines a new class method that allows you to define dynamic methods.
5
+ # Defines a new class method that allows you to define dynamicinstance methods.
6
6
  # Takes a regular expression and a block, which are stored and called later.
7
7
  def matches(regexp, &block)
8
8
  @@match_methods ||= []
@@ -10,18 +10,21 @@ module MatchDef
10
10
  @@match_methods << MatchMethod.new( :matcher => regexp,
11
11
  :proc => block )
12
12
  self.class_eval {
13
- unless respond_to?(:match_method_missing)
13
+ unless method_defined? :method_missing
14
+ def method_missing(meth, *args, &block); super; end
15
+ end
16
+
17
+ unless method_defined?(:match_method_missing)
14
18
  # Defines a +method_missing+ that is aware of the
15
19
  # dynamically-defined methods and will call them if appropriate.
16
- def match_method_missing(message, *args)
20
+ def match_method_missing(message, *args, &block)
17
21
  # Attempt to evaluate this using a MetaMethod
18
22
  result = @@match_methods.find do |mm|
19
23
  if mm.matches?(message)
20
24
  return mm.match(self, message, args)
21
25
  end
22
26
  end
23
- return result if result
24
- return old_method_missing(message, args)
27
+ return result || old_method_missing(message, args, &block)
25
28
  end
26
29
 
27
30
  alias_method :old_method_missing, :method_missing
@@ -32,7 +35,7 @@ module MatchDef
32
35
 
33
36
  # Allows you to delete all defined dynamic methods on a class.
34
37
  # This permits testing.
35
- def reset_meta_methods
38
+ def reset_match_methods
36
39
  @@match_methods = []
37
40
  end
38
41
  end
data/matches.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{matches}
8
- s.version = "1.0.3"
8
+ s.version = "1.0.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Phil Calvin"]
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "README.md",
27
27
  "README.rdoc",
28
28
  "Rakefile",
29
+ "TODO.md",
29
30
  "VERSION",
30
31
  "features/define_matches.feature",
31
32
  "features/step_definitions/method_steps.rb",
data/spec/matches_spec.rb CHANGED
@@ -2,68 +2,130 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe MatchDef do
4
4
  before(:each) do
5
- Hippo.reset_meta_methods
5
+ Hippo.reset_match_methods
6
+
7
+ class Hippo
8
+ def method_missing(message, *args)
9
+ super
10
+ end
11
+
12
+ if method_defined?(:match_method_missing)
13
+ undef match_method_missing
14
+ end
15
+ end
6
16
  end
7
17
 
8
- it "should provide a matches method on classes" do
9
- lambda {
18
+ describe "when defining instance methods" do
19
+
20
+ it "should provide a matches method on classes" do
21
+ lambda {
22
+ Hippo.class_eval do
23
+ matches /foo/
24
+ end
25
+ }.should_not raise_error
26
+ end
27
+
28
+ it "should call the method if it matches" do
10
29
  Hippo.class_eval do
11
- matches /foo/
30
+ matches /bar/ do
31
+ worked
32
+ end
12
33
  end
13
- }.should_not raise_error
14
- end
34
+
35
+ test = Hippo.new
36
+ test.should_receive(:worked).once
37
+ test.bar
38
+ end
15
39
 
16
- it "should call the method if it matches" do
17
- Hippo.class_eval do
18
- matches /bar/ do
19
- worked
40
+ it "should pass in the match groups" do
41
+ Hippo.class_eval do
42
+ matches /bar_(\w+)/ do |activity|
43
+ worked(activity)
44
+ end
20
45
  end
46
+
47
+ test = Hippo.new
48
+ test.should_receive(:worked).once.with('fight')
49
+ test.bar_fight()
21
50
  end
22
51
 
23
- test = Hippo.new
24
- test.should_receive(:worked).once
25
- test.bar
26
- end
27
-
28
- it "should pass in the match groups" do
29
- Hippo.class_eval do
30
- matches /bar_(\w+)/ do |activity|
31
- worked(activity)
52
+ it "should fall through normally if no match" do
53
+ Hippo.class_eval do
54
+ matches /bar_(\w+)/ do |activity|
55
+ worked(activity)
56
+ end
32
57
  end
33
- end
34
58
 
35
- test = Hippo.new
36
- test.should_receive(:worked).once.with('fight')
37
- test.bar_fight()
38
- end
59
+ test = Hippo.new
60
+ test.should_receive(:worked).never
61
+ lambda { test.totally_unmatched }.should raise_error(NoMethodError)
62
+ end
39
63
 
40
- it "should respect an existing method_missing" do
41
- Hippo.class_eval do
42
- def method_missing(message, *args)
43
- affirm(message)
44
- end
64
+ it "should respect an existing method_missing" do
65
+ Hippo.class_eval do
66
+ def method_missing(message, *args)
67
+ affirm(message)
68
+ end
45
69
 
46
- matches /second/ do
47
- affirm(:second)
70
+ matches /second/ do
71
+ affirm(:second)
72
+ end
48
73
  end
74
+
75
+ test = Hippo.new
76
+ test.should_receive(:affirm).once.with(:first)
77
+ test.should_receive(:affirm).once.with(:second)
78
+ test.first()
79
+ test.second()
49
80
  end
81
+
82
+ it "should not pollute other classes" do
83
+ Hippo.class_eval do
84
+ matches /second/ do
85
+ throw "Should never be reached"
86
+ end
87
+ end
50
88
 
51
- test = Hippo.new
52
- test.should_receive(:affirm).once.with(:first)
53
- test.should_receive(:affirm).once.with(:second)
54
- test.first()
55
- test.second()
89
+ test = Rhino.new
90
+ lambda { test.second() }.should raise_error
91
+ end
92
+
56
93
  end
57
94
 
58
- it "should not pollute other classes" do
59
- Hippo.class_eval do
60
- matches /second/ do
61
- throw "Should never be reached"
95
+ describe "when defining class methods" do
96
+
97
+ it "should call the method if it matches" do
98
+ Hippo.should_receive(:worked).once
99
+ class Hippo
100
+ class << self
101
+ matches /foo/ do
102
+ worked
103
+ end
104
+ end
62
105
  end
106
+
107
+ Hippo.foo
63
108
  end
64
109
 
65
- test = Rhino.new
66
- lambda { test.second() }.should raise_error
110
+ it "should differentiate between class and instance methods" do
111
+ class Hippo
112
+ matches /foo/ do
113
+ worked
114
+ end
115
+
116
+ class << self
117
+ matches /foo/ do
118
+ failed
119
+ end
120
+ end
121
+ end
122
+
123
+ herman = Hippo.new
124
+ Hippo.should_receive(:failed).never
125
+ herman.should_receive(:worked).once
126
+
127
+ herman.foo
128
+ end
67
129
  end
68
130
  end
69
131
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matches
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Calvin
@@ -52,6 +52,7 @@ files:
52
52
  - README.md
53
53
  - README.rdoc
54
54
  - Rakefile
55
+ - TODO.md
55
56
  - VERSION
56
57
  - features/define_matches.feature
57
58
  - features/step_definitions/method_steps.rb