eager_beaver 0.0.1 → 0.0.2
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/.rspec +2 -0
- data/README.md +215 -19
- data/eager_beaver.gemspec +2 -0
- data/lib/eager_beaver.rb +9 -9
- data/lib/eager_beaver/method_matcher.rb +39 -7
- data/lib/eager_beaver/version.rb +1 -1
- data/spec/eager_beaver/context_spec.rb +78 -0
- data/spec/eager_beaver/eager_beaver_spec.rb +135 -0
- data/spec/spec_helper.rb +19 -0
- metadata +27 -4
data/.rspec
ADDED
data/README.md
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
# EagerBeaver
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
`EagerBeaver` provides an interface for adding `#method_missing`-related abilities
|
6
|
+
to a class or module.
|
7
|
+
|
8
|
+
## Key Features
|
9
|
+
|
10
|
+
- Method matchers can be added dynamically and cumulatively, reducing the risk
|
11
|
+
of accidentally altering or removing previously-added functionality.
|
12
|
+
- Matched methods are automatically reflected in calls to `#respond_to?` and
|
13
|
+
`#method`, DRY-ing up code by centralizing method-matching logic.
|
14
|
+
- Matched methods are automatically added to the including class/module and
|
15
|
+
invoked. Subsequent calls won't trigger `#method_missing`.
|
16
|
+
- When a method cannot be matched, `super`'s `#method_missing` is automatically
|
17
|
+
invoked.
|
8
18
|
|
9
19
|
## Installation
|
10
20
|
|
@@ -22,6 +32,12 @@ Or install it yourself as:
|
|
22
32
|
|
23
33
|
## Usage
|
24
34
|
|
35
|
+
### Inclusion
|
36
|
+
|
37
|
+
Any class or module which includes `EagerBeaver` will gain the `add_method_matcher`
|
38
|
+
pseudo-keyword, which [indirectly] yields an `EagerBeaver::MethodMatcher` to the
|
39
|
+
given block:
|
40
|
+
|
25
41
|
```ruby
|
26
42
|
require 'eager_beaver'
|
27
43
|
|
@@ -29,27 +45,207 @@ class NeedsMethods
|
|
29
45
|
include EagerBeaver
|
30
46
|
|
31
47
|
add_method_matcher do |mm|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
48
|
+
...
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
In this case, the resulting `MethodMatcher` is added to the end of a `MethodMatcher` list
|
54
|
+
associated with `NeedsMethods`.
|
55
|
+
|
56
|
+
Each `MethodMatcher` needs two things: a lambda for matching missing method names
|
57
|
+
and a lambda for creating the code for any method names it matches:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
add_method_matcher do |mm|
|
61
|
+
mm.match = lambda { ... }
|
62
|
+
mm.new_method_code = lambda { ...}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
### Matching
|
68
|
+
|
69
|
+
The `match` lambda should return a true value if the missing method name is one
|
70
|
+
can be handled by the `MethodMatcher`. The following example will match
|
71
|
+
missing methods of the form `#make_<attr_name>`:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
mm.match = lambda {
|
75
|
+
/\Amake_(\w+)\z/ =~ context.missing_method_name
|
76
|
+
context.attr_name = Regexp.last_match ? Regexp.last_match[1] : nil
|
77
|
+
return Regexp.last_match
|
78
|
+
}
|
79
|
+
```
|
80
|
+
|
81
|
+
### Context
|
82
|
+
|
83
|
+
As the example shows, each `MethodMatcher` contains a `context` which provides:
|
84
|
+
|
85
|
+
- the name of the missing method (`context.missing_method_name`)
|
86
|
+
- the original method receiver instance (`context.original_receiver`)
|
87
|
+
- a place to stash information (`context.<attr_name>` and `context.<attr_name>=`)
|
88
|
+
|
89
|
+
This `context` is shared between the `match` and `new_method_code` lambdas, and
|
90
|
+
is reset between uses of each `MethodMatcher`.
|
91
|
+
|
92
|
+
### Code Generation
|
93
|
+
|
94
|
+
The `new_method_code` lambda should return a string which will create the
|
95
|
+
missing method in `NeedsMethods`:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
mm.new_method_code = lambda {
|
99
|
+
code = %Q{
|
100
|
+
def #{context.missing_method_name}(arg)
|
101
|
+
puts "method \##{context.missing_method_name} has been called"
|
102
|
+
puts "\##{context.missing_method_name} was originally called on #{context.original_receiver}"
|
103
|
+
puts "#{context.attr_name} was passed from matching to code generation"
|
104
|
+
puts "the current call has arguments: \#{arg}"
|
105
|
+
return "result = \#{arg}"
|
41
106
|
end
|
42
107
|
}
|
43
|
-
|
108
|
+
return code
|
109
|
+
}
|
110
|
+
```
|
111
|
+
|
112
|
+
As the example shows, it is perfectly reasonable to take advantage of work done
|
113
|
+
by the `match` lambda (in this case, the parsing of `<attr_name>`).
|
114
|
+
|
115
|
+
After the generated code is inserted into `NeedsMethods`, the missing method
|
116
|
+
call is resent to the original receiver.
|
117
|
+
|
118
|
+
### Complete Example
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
require 'eager_beaver'
|
122
|
+
|
123
|
+
class NeedsMethods
|
124
|
+
include EagerBeaver
|
125
|
+
|
126
|
+
add_method_matcher do |mm|
|
127
|
+
mm.match = lambda {
|
128
|
+
/\Amake_(\w+)\z/ =~ context.missing_method_name
|
129
|
+
context.attr_name = Regexp.last_match ? Regexp.last_match[1] : nil
|
130
|
+
return Regexp.last_match
|
131
|
+
}
|
132
|
+
|
133
|
+
mm.new_method_code = lambda {
|
134
|
+
code = %Q{
|
135
|
+
def #{context.missing_method_name}(arg)
|
136
|
+
puts "method \##{context.missing_method_name} has been called"
|
137
|
+
puts "\##{context.missing_method_name} was originally called on #{context.original_receiver}"
|
138
|
+
puts "#{context.attr_name} was passed from matching to code generation"
|
139
|
+
puts "the current call has arguments: \#{arg}"
|
140
|
+
return "result = \#{arg}"
|
141
|
+
end
|
142
|
+
}
|
143
|
+
return code
|
144
|
+
}
|
44
145
|
end
|
45
146
|
end
|
147
|
+
```
|
148
|
+
|
149
|
+
## Execution
|
150
|
+
|
151
|
+
Given the `NeedsMethods` class in the example above, let's work through the
|
152
|
+
following code:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
nm1 = NeedsMethods.new
|
156
|
+
puts nm1.make_thingy(10)
|
157
|
+
puts nm1.make_widget("hi")
|
158
|
+
|
159
|
+
nm2 = NeedsMethods.new
|
160
|
+
puts nm2.make_thingy(20)
|
161
|
+
puts nm2.make_widget("hello")
|
162
|
+
|
163
|
+
nm2.dont_make_this
|
164
|
+
```
|
165
|
+
|
166
|
+
As instances of `NeedsMethods`, `nm1` and `nm2` will automatically hande
|
167
|
+
methods of the form `#make_<attr_name>`.
|
168
|
+
|
169
|
+
The line:
|
170
|
+
```ruby
|
171
|
+
puts nm1.make_thingy(10)
|
172
|
+
```
|
173
|
+
will trigger `nm1`'s `#method_missing`, which `NeedsMethods` implements thanks to
|
174
|
+
`EagerBeaver`. Each `MethodMatcher` associated with `EagerBeaver` is run against
|
175
|
+
the method name `make_thingy`, and sure enough one matches. This causes the
|
176
|
+
following methods to be inserted to `NeedsMethods`:
|
177
|
+
```ruby
|
178
|
+
def make_thingy(arg)
|
179
|
+
puts "method #make_thingy has been called"
|
180
|
+
puts "#make_thingy was originally called on #<NeedsMethods:0x007fa1bc17f498>"
|
181
|
+
puts "thingy was passed from matching to code generation"
|
182
|
+
puts "the current call has arguments: #{arg}"
|
183
|
+
return "result = #{arg}"
|
184
|
+
end
|
185
|
+
```
|
186
|
+
and when `#make_thingy` is resent to `nm1`, the existing method is called and
|
187
|
+
outputs:
|
188
|
+
|
189
|
+
> method \#make_thingy has been called<br/>
|
190
|
+
> \#make_thingy was originally called on \#\<NeedsMethods:0x007fa1bc17f498\><br/>
|
191
|
+
> thingy was passed from matching to code generation<br/>
|
192
|
+
> the current call has arguments: 10<br/>
|
193
|
+
> result = 10
|
194
|
+
|
195
|
+
Similarly, the line:
|
196
|
+
```ruby
|
197
|
+
puts nm1.make_widget("hi")
|
198
|
+
```
|
199
|
+
generates the code:
|
200
|
+
```ruby
|
201
|
+
def make_widget(arg)
|
202
|
+
puts "method #make_widget has been called"
|
203
|
+
puts "#make_widget was originally called on #<NeedsMethods:0x007fa1bc17f498>"
|
204
|
+
puts "widget was passed from matching to code generation"
|
205
|
+
puts "the current call has arguments: #{arg}"
|
206
|
+
return "result = #{arg}"
|
207
|
+
end
|
208
|
+
```
|
209
|
+
and outputs:
|
210
|
+
> method \#make_widget has been called<br/>
|
211
|
+
> \#make_widget was originally called on \#\<NeedsMethods:0x007fa1bc17f498\><br/>
|
212
|
+
> widget was passed from matching to code generation<br/>
|
213
|
+
> the current call has arguments: hi<br/>
|
214
|
+
> result = hi
|
215
|
+
|
216
|
+
Note that the following lines do NOT trigger `#method_missing` because both methods
|
217
|
+
have already been added to `NeedsMethods`:
|
218
|
+
```ruby
|
219
|
+
puts nm2.make_thingy(20)
|
220
|
+
puts nm2.make_widget("hello")
|
221
|
+
```
|
222
|
+
This can be seen by examining the identity of the original receiver in the output:
|
46
223
|
|
47
|
-
|
224
|
+
> **method \#make_thingy has been called**<br/>
|
225
|
+
> **\#make_thingy was originally called on \#\<NeedsMethods:0x007fa1bc17f498\>**<br/>
|
226
|
+
> **thingy was passed from matching to code generation**<br/>
|
227
|
+
> the current call has arguments: 20<br/>
|
228
|
+
> result = 20
|
48
229
|
|
49
|
-
|
50
|
-
|
51
|
-
|
230
|
+
> **method \#make_widget has been called**<br/>
|
231
|
+
> **\#make_widget was originally called on \#\<NeedsMethods:0x007fa1bc17f498\>**<br/>
|
232
|
+
> **widget was passed from matching to code generation**<br/>
|
233
|
+
> the current call has arguments: hello<br/>
|
234
|
+
> result = hello
|
235
|
+
|
236
|
+
String substitutions which were part of the generated code body (emphasized)
|
237
|
+
reflect the circumstances of the first set of method calls, as opposed to
|
238
|
+
those which reflect the current call's argument.
|
239
|
+
|
240
|
+
Finally, the call:
|
52
241
|
```
|
242
|
+
nm2.dont_make_this
|
243
|
+
```
|
244
|
+
will cause `NeedsMethods` to examine all of its `MethodMatcher`s and finally call
|
245
|
+
`super`'s `#method_missing`. Because no superclass of `NeedsMethods` handles
|
246
|
+
`#dont_make_this`, the output is:
|
247
|
+
|
248
|
+
> undefined method `dont_make_this' for \#\<NeedsMethods:0x007f8e2b991f90\> (NoMethodError)
|
53
249
|
|
54
250
|
## Contributing
|
55
251
|
|
data/eager_beaver.gemspec
CHANGED
@@ -12,6 +12,8 @@ Gem::Specification.new do |gem|
|
|
12
12
|
generation as well. Generated methods are added to the missing method receiver.}
|
13
13
|
gem.homepage = "http://github.com/kevinburleigh75/eager_beaver"
|
14
14
|
|
15
|
+
gem.add_development_dependency "rspec", ["~>2.13.0"]
|
16
|
+
|
15
17
|
gem.files = `git ls-files`.split($\)
|
16
18
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
19
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
data/lib/eager_beaver.rb
CHANGED
@@ -9,14 +9,12 @@ module EagerBeaver
|
|
9
9
|
|
10
10
|
def method_missing(method_name, *args, &block)
|
11
11
|
self.class.method_matchers.each do |method_matcher|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
self.class.class_eval method_string, __FILE__, __LINE__ + 1
|
19
|
-
end
|
12
|
+
mm = method_matcher.dup
|
13
|
+
self.class.context = mm
|
14
|
+
mm.original_receiver = self
|
15
|
+
if mm.match?(method_name)
|
16
|
+
method_string = mm.evaluate mm.new_method_code_maker
|
17
|
+
self.class.class_eval method_string, __FILE__, __LINE__ + 1
|
20
18
|
return self.send(method_name, *args, &block)
|
21
19
|
end
|
22
20
|
end
|
@@ -36,8 +34,10 @@ module EagerBeaver
|
|
36
34
|
end
|
37
35
|
|
38
36
|
def add_method_matcher(&block)
|
39
|
-
method_matchers << MethodMatcher.new(block)
|
37
|
+
method_matchers << MethodMatcher.new(&block)
|
40
38
|
end
|
39
|
+
|
40
|
+
attr_accessor :context
|
41
41
|
end
|
42
42
|
|
43
43
|
end
|
@@ -2,27 +2,59 @@ module EagerBeaver
|
|
2
2
|
|
3
3
|
class MethodMatcher
|
4
4
|
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :original_receiver
|
6
6
|
attr_accessor :matcher
|
7
|
-
attr_accessor :new_method
|
8
7
|
attr_accessor :new_method_code_maker
|
9
8
|
attr_accessor :missing_method_name
|
10
9
|
|
11
|
-
def initialize(block)
|
10
|
+
def initialize(&block)
|
12
11
|
block.call(self)
|
13
12
|
|
14
|
-
raise
|
13
|
+
raise "matcher must be given" \
|
15
14
|
if matcher.nil?
|
16
|
-
raise
|
17
|
-
|
15
|
+
raise "matcher lmust be a lambda" \
|
16
|
+
unless matcher.lambda?
|
17
|
+
|
18
|
+
raise "new_method_code_maker must be given" \
|
19
|
+
if new_method_code_maker.nil?
|
20
|
+
raise "new_method_code_maker must be a lambda" \
|
21
|
+
unless new_method_code_maker.lambda?
|
18
22
|
|
19
23
|
self
|
20
24
|
end
|
21
25
|
|
26
|
+
def match=(lambda_proc)
|
27
|
+
self.matcher = lambda_proc
|
28
|
+
end
|
29
|
+
|
22
30
|
def match?(method_name)
|
23
31
|
self.missing_method_name = method_name.to_s
|
24
|
-
|
32
|
+
return evaluate(matcher)
|
33
|
+
end
|
34
|
+
|
35
|
+
def new_method_code=(lambda_proc)
|
36
|
+
self.new_method_code_maker = lambda_proc
|
25
37
|
end
|
38
|
+
|
39
|
+
def evaluate(inner)
|
40
|
+
outer = lambda { |*args|
|
41
|
+
args.shift
|
42
|
+
inner.call(*args)
|
43
|
+
}
|
44
|
+
self.instance_eval &outer
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(method_name, *args, &block)
|
48
|
+
if /\A(?<attr_name>\w+)=?\z/ =~ method_name
|
49
|
+
code = %Q{
|
50
|
+
attr_accessor :#{attr_name}
|
51
|
+
}
|
52
|
+
self.singleton_class.instance_eval code, __FILE__, __LINE__ + 1
|
53
|
+
return self.send(method_name, *args, &block)
|
54
|
+
end
|
55
|
+
super
|
56
|
+
end
|
57
|
+
|
26
58
|
end
|
27
59
|
|
28
60
|
end
|
data/lib/eager_beaver/version.rb
CHANGED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "matcher context" do
|
4
|
+
|
5
|
+
describe "#missing_method_name" do
|
6
|
+
it "provides the name of the missing method" do
|
7
|
+
klass = Class.new do
|
8
|
+
include EagerBeaver
|
9
|
+
|
10
|
+
add_method_matcher do |mm|
|
11
|
+
mm.matcher = lambda {
|
12
|
+
raise context.missing_method_name \
|
13
|
+
unless context.missing_method_name == "aaa"
|
14
|
+
/\Aaaa\z/ =~ context.missing_method_name
|
15
|
+
}
|
16
|
+
mm.new_method_code = lambda {
|
17
|
+
raise context.missing_method_name \
|
18
|
+
unless context.missing_method_name == "aaa"
|
19
|
+
%Q{
|
20
|
+
def #{context.missing_method_name}
|
21
|
+
end
|
22
|
+
}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
expect{ klass.new.aaa }.to_not raise_exception
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#original_receiver" do
|
31
|
+
it "provides the orignal method receiver" do
|
32
|
+
klass = Class.new do
|
33
|
+
include EagerBeaver
|
34
|
+
|
35
|
+
add_method_matcher do |mm|
|
36
|
+
mm.matcher = lambda {
|
37
|
+
/\Aaaa\z/ =~ context.missing_method_name
|
38
|
+
}
|
39
|
+
mm.new_method_code = lambda {
|
40
|
+
%Q{
|
41
|
+
def #{context.missing_method_name}
|
42
|
+
#{context.original_receiver.__id__}
|
43
|
+
end
|
44
|
+
}
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
instance = klass.new
|
50
|
+
instance.aaa.should equal instance.__id__
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#<attr_name> and #<attr_name>=" do
|
55
|
+
it "provide a way to pass data between method matching and code generation" do
|
56
|
+
klass = Class.new do
|
57
|
+
include EagerBeaver
|
58
|
+
|
59
|
+
add_method_matcher do |mm|
|
60
|
+
mm.matcher = lambda {
|
61
|
+
context.my_data = "hello"
|
62
|
+
/\Aaaa\z/ =~ context.missing_method_name
|
63
|
+
}
|
64
|
+
mm.new_method_code = lambda {
|
65
|
+
%Q{
|
66
|
+
def #{context.missing_method_name}
|
67
|
+
"#{context.my_data}"
|
68
|
+
end
|
69
|
+
}
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
klass.new.aaa.should == "hello"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EagerBeaver do
|
4
|
+
|
5
|
+
describe ".included" do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@klass = Class.new do
|
9
|
+
include EagerBeaver
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "adds Includer.add_method_matcher" do
|
14
|
+
expect(@klass.methods).to include :add_method_matcher
|
15
|
+
end
|
16
|
+
|
17
|
+
it "adds Includer.method_matchers" do
|
18
|
+
expect(@klass.methods).to include :method_matchers
|
19
|
+
end
|
20
|
+
|
21
|
+
it "adds Includer.context" do
|
22
|
+
expect(@klass.methods).to include :context
|
23
|
+
end
|
24
|
+
|
25
|
+
it "adds Includer.context=" do
|
26
|
+
expect(@klass.methods).to include :context=
|
27
|
+
end
|
28
|
+
|
29
|
+
it "adds Includer#method_missing" do
|
30
|
+
expect(@klass.instance_methods(:false)).to include :method_missing
|
31
|
+
end
|
32
|
+
|
33
|
+
it "adds Includer#respond_to_missing?" do
|
34
|
+
expect(@klass.instance_methods(:false)).to include :respond_to_missing?
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#add_method_matcher" do
|
40
|
+
|
41
|
+
it "registers a new method matcher" do
|
42
|
+
klass = Class.new do
|
43
|
+
include EagerBeaver
|
44
|
+
|
45
|
+
add_method_matcher do |mm|
|
46
|
+
mm.matcher = lambda { true }
|
47
|
+
mm.new_method_code = lambda {
|
48
|
+
return %Q{
|
49
|
+
def #{context.missing_method_name}
|
50
|
+
end
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
klass.method_matchers.size.should == 1
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#method_missing" do
|
62
|
+
|
63
|
+
context "method matching" do
|
64
|
+
|
65
|
+
it "invokes the first matching matcher" do
|
66
|
+
klass = Class.new do
|
67
|
+
include EagerBeaver
|
68
|
+
|
69
|
+
add_method_matcher do |mm|
|
70
|
+
mm.matcher = lambda { /\Aaaa\z/ =~ context.missing_method_name }
|
71
|
+
mm.new_method_code = lambda {
|
72
|
+
%Q{
|
73
|
+
def #{context.missing_method_name}
|
74
|
+
1
|
75
|
+
end
|
76
|
+
}
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
add_method_matcher do |mm|
|
81
|
+
mm.matcher = lambda { /\Abbb\z/ =~ context.missing_method_name }
|
82
|
+
mm.new_method_code = lambda {
|
83
|
+
%Q{
|
84
|
+
def #{context.missing_method_name}
|
85
|
+
2
|
86
|
+
end
|
87
|
+
}
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
add_method_matcher do |mm|
|
92
|
+
mm.matcher = lambda { /\Abbb\z/ =~ context.missing_method_name }
|
93
|
+
mm.new_method_code = lambda {
|
94
|
+
%Q{
|
95
|
+
def #{context.missing_method_name}
|
96
|
+
3
|
97
|
+
end
|
98
|
+
}
|
99
|
+
}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
klass.new.bbb.should == 2
|
104
|
+
end
|
105
|
+
|
106
|
+
it "calls super #method_missing if no matcher matches" do
|
107
|
+
klass1 = Class.new do
|
108
|
+
def method_missing(method_name, *args, &block)
|
109
|
+
10
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
klass2 = Class.new(klass1) do
|
114
|
+
include EagerBeaver
|
115
|
+
|
116
|
+
add_method_matcher do |mm|
|
117
|
+
mm.matcher = lambda { /\Aaaa\z/ =~ context.missing_method_name }
|
118
|
+
mm.new_method_code = lambda {
|
119
|
+
%Q{
|
120
|
+
def #{context.missing_method_name}
|
121
|
+
1
|
122
|
+
end
|
123
|
+
}
|
124
|
+
}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
klass2.new.bbb.should == 10
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'eager_beaver'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eager_beaver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
13
|
-
dependencies:
|
12
|
+
date: 2013-04-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.13.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.13.0
|
14
30
|
description: Facilitates method_missing, respond_to_missing?, and method-generation
|
15
31
|
activities
|
16
32
|
email:
|
@@ -20,6 +36,7 @@ extensions: []
|
|
20
36
|
extra_rdoc_files: []
|
21
37
|
files:
|
22
38
|
- .gitignore
|
39
|
+
- .rspec
|
23
40
|
- Gemfile
|
24
41
|
- LICENSE
|
25
42
|
- README.md
|
@@ -28,6 +45,9 @@ files:
|
|
28
45
|
- lib/eager_beaver.rb
|
29
46
|
- lib/eager_beaver/method_matcher.rb
|
30
47
|
- lib/eager_beaver/version.rb
|
48
|
+
- spec/eager_beaver/context_spec.rb
|
49
|
+
- spec/eager_beaver/eager_beaver_spec.rb
|
50
|
+
- spec/spec_helper.rb
|
31
51
|
homepage: http://github.com/kevinburleigh75/eager_beaver
|
32
52
|
licenses: []
|
33
53
|
post_install_message:
|
@@ -56,4 +76,7 @@ summary: ! 'Facilitates method_missing, respond_to_missing?, and method-generati
|
|
56
76
|
activities, such as registering with #method_missing and #respond_to_missing? are
|
57
77
|
handled automatically. Facilitates method name pattern-specific method generation
|
58
78
|
as well. Generated methods are added to the missing method receiver.'
|
59
|
-
test_files:
|
79
|
+
test_files:
|
80
|
+
- spec/eager_beaver/context_spec.rb
|
81
|
+
- spec/eager_beaver/eager_beaver_spec.rb
|
82
|
+
- spec/spec_helper.rb
|