after_do 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/README.md +33 -96
- data/lib/after_do.rb +77 -120
- data/lib/after_do/version.rb +1 -1
- data/samples/with_module.rb +34 -0
- data/spec/after_do_spec.rb +103 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d5697c2f0c8130887073ed0072678789e8602cc
|
4
|
+
data.tar.gz: 40ad3b18353a8233045639effb09e95df96ab3b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 404f4d82231b298a86d8e6699054dd0ca799a1b0e8ad85690ba2d308bb3b2d6b44564862da3440306f4ddde4ccb5e4a86f7e468a4a61cd22217c8a0ce99ac81e
|
7
|
+
data.tar.gz: e6e641a679300989f91a1185d546c2dca3ac2b3d31dbdbf5b6df7ed01bb8f3a690c99bf155bc104ef0f671bf3c25fca3dcb2bf6e769a320c066cc906a6f59020
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,18 +1,27 @@
|
|
1
1
|
# after_do [![Gem Version](https://badge.fury.io/rb/after_do.png)](http://badge.fury.io/rb/after_do)[![Build Status](https://travis-ci.org/PragTob/after_do.png?branch=master)](https://travis-ci.org/PragTob/after_do)[![Code Climate](https://codeclimate.com/github/PragTob/after_do.png)](https://codeclimate.com/github/PragTob/after_do)[![Coverage Status](https://coveralls.io/repos/PragTob/after_do/badge.png)](https://coveralls.io/r/PragTob/after_do)
|
2
2
|
|
3
|
-
after_do is simple gem, that allows you to execute
|
3
|
+
after_do is simple gem, that helps you fight cross-cutting concerns with an approach similar to Aspect Oriented Programming (AOP). after_do allows you to execute blocks (callbacks) after/before specific methods of a class or a module are called.
|
4
|
+
|
5
|
+
If the class extends `AfterDo` you can simply do this by
|
4
6
|
|
5
7
|
```
|
6
8
|
MyClass.after :some_method do whatever_you_want end
|
7
9
|
```
|
8
10
|
|
9
|
-
|
11
|
+
Some facts about after_do:
|
12
|
+
|
13
|
+
* no external runtime dependencies
|
14
|
+
* small code base: code is around 120 lines of code with blank lines, comments and everything - simplecov reports less than 60 relevant lines of code
|
15
|
+
* simple DSL
|
16
|
+
* no monkey patching
|
17
|
+
|
18
|
+
## Why would you want to do this?
|
19
|
+
Well to fight cross-cutting concerns. These are concerns in an applications that apply to multiple objects (e.g. they cross-cut).
|
20
|
+
A popular example is logging - you might want to log multiple actions of different classes but logging is not the primary concern of the class in question. With logging you litter all your code with logging statements - that concern is spread over many files and adds unnecessary noise to them. With after_do you could put all the logging in one file. Other use cases include gathering business statistics or redrawing timing of elements.
|
10
21
|
This should generally not be done to alter behavior of the class and its instances - this makes programs more confusing rather than easier to understand.
|
11
22
|
|
12
23
|
The idea for this is inspired by Aspect Oriented Programming - e.g. do something when specific methods are executed. However I doubt that this formally fulfills the lingo (join points, aspects, advice...)
|
13
24
|
|
14
|
-
after_do has no external runtime dependencies and the code is around 160 lines of code (blank lines and documentation included) with lots of small methods. So simplecov reports there are a little above 70 relevant lines code (it ignores blank lines, docs etc.).
|
15
|
-
|
16
25
|
## Installation
|
17
26
|
|
18
27
|
Add this line to your application's Gemfile:
|
@@ -92,7 +101,7 @@ MyClass.after :two_arg_method do |argument_one, argument_2| something end
|
|
92
101
|
The object itself is passed in as the last block argument, so if you just care about the object you can do:
|
93
102
|
|
94
103
|
```ruby
|
95
|
-
MyClass.after :two_arg_method do |*, obj| fancy_stuff(obj)
|
104
|
+
MyClass.after :two_arg_method do |*, obj| fancy_stuff(obj) end
|
96
105
|
```
|
97
106
|
|
98
107
|
Of course you can get a hold of the method arguments and the object:
|
@@ -103,41 +112,7 @@ MyClass.after :two_arg_method do |arg1, arg2, obj| something(arg1, arg2, obj) en
|
|
103
112
|
|
104
113
|
If you do not want to get a hold of the method arguments or the object, then you can just don't care about the block parameters :-)
|
105
114
|
|
106
|
-
|
107
|
-
|
108
|
-
```ruby
|
109
|
-
class Example
|
110
|
-
def zero
|
111
|
-
# ...
|
112
|
-
end
|
113
|
-
|
114
|
-
def two(a, b)
|
115
|
-
# ...
|
116
|
-
end
|
117
|
-
|
118
|
-
def value
|
119
|
-
'some value'
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
Example.extend AfterDo
|
124
|
-
|
125
|
-
Example.after :zero do puts 'Hello!' end
|
126
|
-
Example.after :zero do |obj| puts obj.value end
|
127
|
-
Example.after :two do |first, second| puts first + ' ' + second end
|
128
|
-
Example.after :two do |a, b, obj| puts a + ' ' + b + ' ' + obj.value end
|
129
|
-
Example.after :two do |*, obj| puts 'just ' + obj.value end
|
130
|
-
|
131
|
-
e = Example.new
|
132
|
-
e.zero
|
133
|
-
e.two 'one', 'two'
|
134
|
-
# prints:
|
135
|
-
# Hello!
|
136
|
-
# some value
|
137
|
-
# one two
|
138
|
-
# one two some value
|
139
|
-
# just some value
|
140
|
-
```
|
115
|
+
Check out the [getting a hold sample](https://github.com/PragTob/after_do/blob/master/samples/getting_a_hold.rb) for more.
|
141
116
|
|
142
117
|
### Attaching a callback to multiple methods
|
143
118
|
|
@@ -216,41 +191,22 @@ class MyClass
|
|
216
191
|
end
|
217
192
|
```
|
218
193
|
|
219
|
-
|
194
|
+
Check out the [within class sample](https://github.com/PragTob/after_do/blob/master/samples/within_class.rb) for a more complete example.
|
195
|
+
|
196
|
+
### Working with modules
|
197
|
+
|
198
|
+
after_do works with modules just like it works with classes from version 0.3.0 onwards. E.g. you can just do:
|
220
199
|
|
221
200
|
```ruby
|
222
|
-
class
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
# ...
|
227
|
-
end
|
228
|
-
|
229
|
-
def remove_member(member)
|
230
|
-
# ..
|
231
|
-
end
|
232
|
-
|
233
|
-
def change_name(new_name)
|
234
|
-
# ..
|
235
|
-
end
|
236
|
-
|
237
|
-
def save
|
238
|
-
# ..
|
239
|
-
puts 'saving...'
|
240
|
-
end
|
241
|
-
|
242
|
-
after :add_member, :remove_member, :change_name do |*, team| team.save end
|
243
|
-
end
|
201
|
+
class MyClass
|
202
|
+
include MyModule
|
203
|
+
# ....
|
204
|
+
end
|
244
205
|
|
245
|
-
|
246
|
-
|
247
|
-
team.change_name 'Ruby Cherries'
|
248
|
-
team.remove_member 'Guilia'
|
206
|
+
MyModule.extend AfterDo
|
207
|
+
MyModule.after :some_method do cool_stuff end
|
249
208
|
|
250
|
-
#
|
251
|
-
# saving...
|
252
|
-
# saving...
|
253
|
-
# saving...
|
209
|
+
MyClass.new.some_method # triggers callback
|
254
210
|
```
|
255
211
|
|
256
212
|
### Removing callbacks
|
@@ -274,31 +230,12 @@ When an error occurs during one of the callbacks that are attached to a method i
|
|
274
230
|
|
275
231
|
Yes. It works just like the `after` method, but the callbacks are executed before the original method is called. You can also mix and match before and after calls.
|
276
232
|
|
277
|
-
Before for me is a far less common use case, that's why it was only added later (in the 0.2 release).
|
278
|
-
|
279
|
-
Here is a small sample:
|
280
|
-
|
281
233
|
```ruby
|
282
|
-
|
283
|
-
|
284
|
-
class MyClass
|
285
|
-
attr_accessor :value
|
286
|
-
end
|
287
|
-
|
288
|
-
MyClass.extend AfterDo
|
289
|
-
MyClass.after :value= do |*, obj| puts 'after: ' + obj.value.to_s end
|
290
|
-
MyClass.before :value= do |*, obj| puts 'before: ' + obj.value.to_s end
|
234
|
+
MyClass.before :a_method do so_much end
|
235
|
+
```
|
291
236
|
|
292
|
-
|
293
|
-
m.value = 'Hello'
|
294
|
-
m.value = 'new value'
|
237
|
+
Check out the [before sample](https://github.com/PragTob/after_do/blob/master/samples/before.rb).
|
295
238
|
|
296
|
-
# Output is:
|
297
|
-
# before:
|
298
|
-
# after: Hello
|
299
|
-
# before: Hello
|
300
|
-
# after: new value
|
301
|
-
```
|
302
239
|
|
303
240
|
### Method granularity
|
304
241
|
|
@@ -325,11 +262,11 @@ A use case I feel this is particularly made for is redrawing. That's what we use
|
|
325
262
|
|
326
263
|
## Does it work with Ruby interpreter X?
|
327
264
|
|
328
|
-
Thanks to the awesome [travis CI](https://travis-ci.org/) the specs are run with MRI 1.9.3, 2.0, the latest jruby and rubinius releases in 1.9 mode. So in short, this should work with all of them and is aimed at doing so :-)
|
265
|
+
Thanks to the awesome [travis CI](https://travis-ci.org/) the specs are run with MRI 1.9.3, 2.0, 2.1, the latest jruby and rubinius releases in 1.9 mode. So in short, this should work with all of them and is aimed at doing so :-)
|
329
266
|
|
330
267
|
## Contributing
|
331
268
|
|
332
|
-
Contributions are very welcome. Whether it's an issue or even a pull request. For pull requests
|
269
|
+
Contributions are very welcome. Whether it's an issue or even a pull request. For pull requests you can use the following flow:
|
333
270
|
|
334
271
|
1. Fork it
|
335
272
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
@@ -339,4 +276,4 @@ Contributions are very welcome. Whether it's an issue or even a pull request. Fo
|
|
339
276
|
|
340
277
|
I'd also really appreciate spec only pull requests or bug reports with a failing spec/minimal example as this makes fixing it a lot easier =)
|
341
278
|
|
342
|
-
Thanks in advance for all contributions of any kind!
|
279
|
+
Thanks in advance for all contributions of any kind!
|
data/lib/after_do.rb
CHANGED
@@ -8,12 +8,6 @@ module AfterDo
|
|
8
8
|
# The prefix for the copies of the original methods made by after_do
|
9
9
|
ALIAS_PREFIX = '__after_do_orig_'
|
10
10
|
|
11
|
-
# ::nodoc::
|
12
|
-
def self.extended(klazz)
|
13
|
-
klazz.send(:include, AfterDo::Instance)
|
14
|
-
klazz.send(:extend, AfterDo::Class)
|
15
|
-
end
|
16
|
-
|
17
11
|
# Raised when trying to attach a callback to a non existing method
|
18
12
|
class NonExistingMethodError < StandardError ; end
|
19
13
|
|
@@ -22,140 +16,103 @@ module AfterDo
|
|
22
16
|
# defined.
|
23
17
|
class CallbackError < StandardError ; end
|
24
18
|
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
# The list might also be an Array.
|
35
|
-
def after(*methods, &block)
|
36
|
-
_after_do_define_callback(:after, methods, block)
|
37
|
-
end
|
38
|
-
|
39
|
-
# This method works much like .after - just that the blocks are executed
|
40
|
-
# before the method is called.
|
41
|
-
def before(*methods, &block)
|
42
|
-
_after_do_define_callback(:before, methods, block)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Removes all callbacks attach to methods in this class.
|
46
|
-
def remove_all_callbacks
|
47
|
-
@_after_do_callbacks = _after_do_basic_hash
|
48
|
-
end
|
19
|
+
# A method to add a callback to a method or a list of methods to be executed
|
20
|
+
# after the original method was executed. E.g.:
|
21
|
+
# MyClass.after :some_method do awesome_stuff end
|
22
|
+
# It can only take a list of methods after which a block should be executed:
|
23
|
+
# MyClass.after :method1, :method2, :method3 do puts 'jay!' end
|
24
|
+
# The list might also be an Array.
|
25
|
+
def after(*methods, &block)
|
26
|
+
_after_do_define_callback(:after, methods, block)
|
27
|
+
end
|
49
28
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
# {after: {method: [callback1, callback2, ...]},
|
56
|
-
# before: {method: [callback1, callback2, ...]}
|
57
|
-
def _after_do_callbacks
|
58
|
-
@_after_do_callbacks || _after_do_basic_hash
|
59
|
-
end
|
29
|
+
# This method works much like .after - just that the blocks are executed
|
30
|
+
# before the method is called.
|
31
|
+
def before(*methods, &block)
|
32
|
+
_after_do_define_callback(:before, methods, block)
|
33
|
+
end
|
60
34
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
_after_do_raise_no_method_specified(type) if methods.empty?
|
66
|
-
methods.each do |method|
|
67
|
-
_after_do_add_callback_to_method(type, method, block)
|
68
|
-
end
|
69
|
-
end
|
35
|
+
# Removes all callbacks attach to methods in this class.
|
36
|
+
def remove_all_callbacks
|
37
|
+
@_after_do_callbacks = _after_do_basic_hash
|
38
|
+
end
|
70
39
|
|
71
|
-
|
72
|
-
|
40
|
+
private
|
41
|
+
def _after_do_define_callback(type, methods, block)
|
42
|
+
@_after_do_callbacks ||= _after_do_basic_hash
|
43
|
+
methods = methods.flatten #in case someone used an Array
|
44
|
+
_after_do_raise_no_method_specified(type) if methods.empty?
|
45
|
+
methods.each do |method|
|
46
|
+
_after_do_add_callback_to_method(type, method, block)
|
73
47
|
end
|
48
|
+
end
|
74
49
|
|
75
|
-
|
76
|
-
|
77
|
-
|
50
|
+
def _after_do_raise_no_method_specified(type)
|
51
|
+
raise ArgumentError, "#{type} takes at least one method name!"
|
52
|
+
end
|
78
53
|
|
79
|
-
|
80
|
-
|
81
|
-
|
54
|
+
def _after_do_basic_hash
|
55
|
+
{after: _after_do_methods_hash, before: _after_do_methods_hash}
|
56
|
+
end
|
82
57
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
87
|
-
@_after_do_callbacks[type][method] << block
|
88
|
-
end
|
58
|
+
def _after_do_methods_hash
|
59
|
+
Hash.new {|hash, key| hash[key] = []}
|
60
|
+
end
|
89
61
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
_after_do_redefine_method_with_callback(method, alias_name)
|
95
|
-
end
|
62
|
+
def _after_do_add_callback_to_method(type, method, block)
|
63
|
+
_after_do_redefine_method(method) unless _after_do_already_redefined?(method)
|
64
|
+
@_after_do_callbacks[type][method] << block
|
65
|
+
end
|
96
66
|
|
97
|
-
|
98
|
-
|
99
|
-
|
67
|
+
def _after_do_already_redefined?(method)
|
68
|
+
private_instance_methods(false).include? _after_do_aliased_name(method)
|
69
|
+
end
|
100
70
|
|
101
|
-
|
102
|
-
|
103
|
-
|
71
|
+
def _after_do_redefine_method(method)
|
72
|
+
_after_do_raise_no_method_error(method) unless _after_do_defined?(method)
|
73
|
+
alias_name = _after_do_aliased_name method
|
74
|
+
_after_do_rename_old_method(method, alias_name)
|
75
|
+
_after_do_redefine_method_with_callback(method, alias_name)
|
76
|
+
end
|
104
77
|
|
105
|
-
|
106
|
-
|
107
|
-
|
78
|
+
def _after_do_defined?(method)
|
79
|
+
method_defined?(method) || private_method_defined?(method)
|
80
|
+
end
|
108
81
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
private new_name
|
113
|
-
end
|
114
|
-
end
|
82
|
+
def _after_do_raise_no_method_error(method)
|
83
|
+
raise NonExistingMethodError, "There is no method #{method} on #{self} to attach a block to with AfterDo"
|
84
|
+
end
|
115
85
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
_after_do_execute_callbacks :before, method, *args
|
120
|
-
return_value = send(alias_name, *args)
|
121
|
-
_after_do_execute_callbacks :after, method, *args
|
122
|
-
return_value
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
86
|
+
def _after_do_aliased_name(symbol)
|
87
|
+
(ALIAS_PREFIX + symbol.to_s).to_sym
|
88
|
+
end
|
126
89
|
|
127
|
-
|
128
|
-
|
129
|
-
|
90
|
+
def _after_do_rename_old_method(old_name, new_name)
|
91
|
+
alias_method new_name, old_name
|
92
|
+
private new_name
|
130
93
|
end
|
131
94
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
_after_do_has_callback_for?(klazz, type, method)
|
140
|
-
end
|
141
|
-
callback_classes.each do |klazz|
|
142
|
-
klazz._after_do_callbacks[type][method].each do |block|
|
143
|
-
_after_do_execute_callback(block, method, *args)
|
144
|
-
end
|
145
|
-
end
|
95
|
+
def _after_do_redefine_method_with_callback(method, alias_name)
|
96
|
+
callback_klazz = self
|
97
|
+
define_method method do |*args|
|
98
|
+
callback_klazz.send(:_after_do_execute_callbacks, :before, method, self, *args)
|
99
|
+
return_value = send(alias_name, *args)
|
100
|
+
callback_klazz.send(:_after_do_execute_callbacks, :after, method, self, *args)
|
101
|
+
return_value
|
146
102
|
end
|
103
|
+
end
|
147
104
|
|
148
|
-
|
149
|
-
|
150
|
-
|
105
|
+
def _after_do_execute_callbacks(type, method, object, *args)
|
106
|
+
@_after_do_callbacks[type][method].each do |block|
|
107
|
+
_after_do_execute_callback(block, method, object, *args)
|
151
108
|
end
|
109
|
+
end
|
152
110
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
end
|
111
|
+
def _after_do_execute_callback(block, method, object, *args)
|
112
|
+
begin
|
113
|
+
block.call *args, object
|
114
|
+
rescue Exception => error
|
115
|
+
raise CallbackError, "A callback block for method #{method} on the instance #{self} with the following arguments: #{args.join(', ')} defined in the file #{block.source_location[0]} in line #{block.source_location[1]} resulted in the following error: #{error.class}: #{error.message} and this backtrace:\n #{error.backtrace.join("\n")}"
|
159
116
|
end
|
160
117
|
end
|
161
118
|
end
|
data/lib/after_do/version.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'after_do'
|
2
|
+
|
3
|
+
module M
|
4
|
+
def method
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class A
|
9
|
+
include M
|
10
|
+
end
|
11
|
+
|
12
|
+
class B
|
13
|
+
include M
|
14
|
+
end
|
15
|
+
|
16
|
+
class C
|
17
|
+
include M
|
18
|
+
|
19
|
+
def method
|
20
|
+
puts 'Overwritten method'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
M.extend AfterDo
|
25
|
+
M.after :method do puts 'method called' end
|
26
|
+
|
27
|
+
A.new.method
|
28
|
+
B.new.method
|
29
|
+
C.new.method # won't call callback since the implementation was overriden
|
30
|
+
|
31
|
+
# Output is:
|
32
|
+
# method called
|
33
|
+
# method called
|
34
|
+
# Overridden method
|
data/spec/after_do_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe AfterDo do
|
4
4
|
|
5
5
|
let(:dummy_instance) {@dummy_class.new}
|
6
|
-
let(:mockie) {double}
|
6
|
+
let(:mockie) {double 'mock block', call: true}
|
7
7
|
|
8
8
|
before :each do
|
9
9
|
redefine_dummy_class
|
@@ -260,6 +260,108 @@ describe AfterDo do
|
|
260
260
|
inherited_instance.zero
|
261
261
|
end
|
262
262
|
end
|
263
|
+
|
264
|
+
describe 'callback on child and parent class' do
|
265
|
+
def redefine_overwriting_child_class
|
266
|
+
@overwriting_child_class = Class.new @dummy_class do
|
267
|
+
def zero
|
268
|
+
0
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
let(:overwriting_child_instance) {@overwriting_child_class.new}
|
274
|
+
|
275
|
+
before :each do
|
276
|
+
@dummy_class.send callback_adder, :zero do mockie.call end
|
277
|
+
redefine_overwriting_child_class
|
278
|
+
@overwriting_child_class.extend AfterDo
|
279
|
+
@overwriting_child_class.send callback_adder, :zero do
|
280
|
+
mockie.call
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'only calls the block once when calling a method on the child' do
|
285
|
+
overwriting_child_instance.zero
|
286
|
+
expect(mockie).to have_received :call
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'only calls the block once when calling a method on the parent' do
|
290
|
+
dummy_instance.zero
|
291
|
+
expect(mockie).to have_received :call
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
describe 'child class calling super' do
|
296
|
+
def redefine_super_child_class
|
297
|
+
@super_child_class = Class.new @dummy_class do
|
298
|
+
def zero
|
299
|
+
super
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
let (:super_child_instance) {@super_child_class.new}
|
305
|
+
|
306
|
+
before :each do
|
307
|
+
redefine_super_child_class
|
308
|
+
@dummy_class.send callback_adder, :zero do mockie.call end
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'still calls the callback block from the parent class' do
|
312
|
+
super_child_instance.zero
|
313
|
+
expect(mockie).to have_received :call
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
describe 'included modules' do
|
319
|
+
def redefine_dummy_module
|
320
|
+
Module.new do
|
321
|
+
def module_method
|
322
|
+
'module'
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
before :each do
|
328
|
+
dummy_module = redefine_dummy_module
|
329
|
+
@bare_class_with_module = Class.new
|
330
|
+
@bare_class_with_module.send(:include, dummy_module)
|
331
|
+
dummy_module.extend AfterDo
|
332
|
+
dummy_module.send callback_adder, :module_method do mockie.call end
|
333
|
+
end
|
334
|
+
|
335
|
+
let(:bare_instance_with_module) {@bare_class_with_module.new}
|
336
|
+
|
337
|
+
it 'executes callbacks from methods of included modules' do
|
338
|
+
bare_instance_with_module.module_method
|
339
|
+
expect(mockie).to have_received(:call)
|
340
|
+
end
|
341
|
+
|
342
|
+
describe '2 modules with the same method' do
|
343
|
+
|
344
|
+
def other_dummy_module
|
345
|
+
Module.new do
|
346
|
+
def module_method
|
347
|
+
'other module'
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
before :each do
|
353
|
+
other_module = other_dummy_module
|
354
|
+
@bare_class_with_module.send(:include, other_module)
|
355
|
+
other_module.extend AfterDo
|
356
|
+
other_module.send callback_adder, :module_method do mockie.call end
|
357
|
+
end
|
358
|
+
|
359
|
+
it 'is still just called once (no super call)' do
|
360
|
+
bare_instance_with_module.module_method
|
361
|
+
expect(mockie).to have_received(:call)
|
362
|
+
end
|
363
|
+
|
364
|
+
end
|
263
365
|
end
|
264
366
|
end
|
265
367
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: after_do
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Pfeiffer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: after_do is a gem that let's you execute a block of your choice after
|
14
14
|
or before a specific method is called on a class. This is inspired by Aspect Oriented
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- samples/error_in_callback.rb
|
37
37
|
- samples/getting_a_hold.rb
|
38
38
|
- samples/inheritance.rb
|
39
|
+
- samples/with_module.rb
|
39
40
|
- samples/within_class.rb
|
40
41
|
- spec/after_do_spec.rb
|
41
42
|
- spec/spec_helper.rb
|
@@ -59,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
60
|
version: '0'
|
60
61
|
requirements: []
|
61
62
|
rubyforge_project:
|
62
|
-
rubygems_version: 2.
|
63
|
+
rubygems_version: 2.1.11
|
63
64
|
signing_key:
|
64
65
|
specification_version: 4
|
65
66
|
summary: after_do allows you to add simple after/before hooks to methods
|