after_do 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/README.md +64 -38
- data/lib/after_do.rb +3 -3
- data/lib/after_do/version.rb +1 -1
- data/samples/singleton.rb +13 -0
- data/spec/after_do_spec.rb +26 -4
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef369cfcfc9f7d0df1898cb7a19063c54d8197ab
|
4
|
+
data.tar.gz: 5e9cb593b171bdb4847f92aaa6ab8bf12baa3186
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d27b6cd8f09cad52b0b721c247c598c18178631133b92f730dcaa8b497acbf78a49d5130f9c48cc79528557a4ee0fb3b222b1783461ba26d030d43bff2b2088
|
7
|
+
data.tar.gz: 7af1a95ded2526a59b80d8bf7059df8906844d64ec9755c831170e5dee3e86e62040d08b4586e01381678449563d1a0579807fce67c722fcd81919d3a479ed3f
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.1.1
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
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 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.
|
3
|
+
after_do is a 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
4
|
|
5
5
|
If the class extends `AfterDo` you can simply do this by
|
6
6
|
|
@@ -10,14 +10,15 @@ MyClass.after :some_method do whatever_you_want end
|
|
10
10
|
|
11
11
|
Some facts about after_do:
|
12
12
|
|
13
|
-
* no
|
13
|
+
* no runtime dependencies
|
14
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
15
|
* simple DSL
|
16
16
|
* no monkey patching
|
17
17
|
|
18
18
|
## Why would you want to do this?
|
19
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.
|
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.
|
21
|
+
With after_do you could put all the logging in one file. Other use cases include gathering business statistics or redrawing timing of elements.
|
21
22
|
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.
|
22
23
|
|
23
24
|
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...)
|
@@ -35,10 +36,14 @@ And then execute:
|
|
35
36
|
Or install it yourself as:
|
36
37
|
|
37
38
|
$ gem install after_do
|
39
|
+
|
40
|
+
And then you have to require the gem before you can use it:
|
41
|
+
|
42
|
+
require 'after_do'
|
38
43
|
|
39
44
|
## Usage
|
40
45
|
|
41
|
-
This section is dedicated to show
|
46
|
+
This section is dedicated to show the general usage and effects of after_do. You can also check out the [samples directory](https://github.com/PragTob/after_do/tree/master/samples) or the [specs](https://github.com/PragTob/after_do/blob/master/spec/after_do_spec.rb) in the spec folder.
|
42
47
|
|
43
48
|
### General usage
|
44
49
|
|
@@ -72,22 +77,8 @@ dog2.bark
|
|
72
77
|
# I just heard a dog bark!
|
73
78
|
# Woooof
|
74
79
|
# I just heard a dog bark!
|
75
|
-
|
76
|
-
```
|
77
|
-
|
78
|
-
### How does it work?
|
79
|
-
|
80
|
-
When you attach a callback to a method with after_do what it basically does is it creates a copy of that method and then redefines the method to basically look like this (pseudo code):
|
81
|
-
|
82
|
-
```ruby
|
83
|
-
execute_before_callbacks
|
84
|
-
return_value = original_method
|
85
|
-
execute_after_callbacks
|
86
|
-
return_value
|
87
80
|
```
|
88
81
|
|
89
|
-
To do this some helper methods are defined in the AfterDo module. As classes have to extend the AfterDo module all the methods that you are not supposed to call yourself are prefixed with `_after_do_` to minimize the risk of method name clashes. The only not prefixed method are `after`, `before` and `remove_all_callbacks`.
|
90
|
-
|
91
82
|
### Getting a hold of the method arguments and the object
|
92
83
|
|
93
84
|
With after_do both the arguments to the method you are attaching the callback to and the object for which the callback is executed are passed into the callback block.
|
@@ -175,9 +166,47 @@ b = B.new
|
|
175
166
|
b.a #prints out: a was called
|
176
167
|
```
|
177
168
|
|
169
|
+
### Working with modules
|
170
|
+
|
171
|
+
after_do works with modules just like it works with classes from version 0.3.0 onwards. E.g. you can just do:
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
class MyClass
|
175
|
+
include MyModule
|
176
|
+
# ....
|
177
|
+
end
|
178
|
+
|
179
|
+
MyModule.extend AfterDo
|
180
|
+
MyModule.after :some_method do cool_stuff end
|
181
|
+
|
182
|
+
MyClass.new.some_method # triggers callback
|
183
|
+
```
|
184
|
+
|
185
|
+
### Working with module/class/singleton methods
|
186
|
+
|
187
|
+
after_do also works with module/class/singleton methods whatever you want to call them, e.g. with `MyModule.method`, thanks to ruby's awesome object/class system. You just have to attach the callbacks to the singleton class of the object (because that's where the "class side" methods are defined).
|
188
|
+
|
189
|
+
Take a look:
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
module M
|
193
|
+
def self.magic
|
194
|
+
puts 'magic'
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
M.singleton_class.extend AfterDo
|
199
|
+
M.singleton_class.after :magic do puts 'after_do is pure magic' end
|
200
|
+
|
201
|
+
M.magic
|
202
|
+
# Output is:
|
203
|
+
magic
|
204
|
+
after_do is pure magic
|
205
|
+
```
|
206
|
+
|
178
207
|
### Usage from within a class
|
179
208
|
|
180
|
-
If you got some repetitive tasks, that
|
209
|
+
If you got some repetitive tasks, that need to be done after/before a lot of methods in a class then you can also use after_do for this. This works a bit like `before_action`/`after_action` (or *_filter in the Rails 3 lingo) which you might know from Ruby on Rails.
|
181
210
|
|
182
211
|
E.g. like this:
|
183
212
|
|
@@ -193,21 +222,6 @@ end
|
|
193
222
|
|
194
223
|
Check out the [within class sample](https://github.com/PragTob/after_do/blob/master/samples/within_class.rb) for a more complete example.
|
195
224
|
|
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:
|
199
|
-
|
200
|
-
```ruby
|
201
|
-
class MyClass
|
202
|
-
include MyModule
|
203
|
-
# ....
|
204
|
-
end
|
205
|
-
|
206
|
-
MyModule.extend AfterDo
|
207
|
-
MyModule.after :some_method do cool_stuff end
|
208
|
-
|
209
|
-
MyClass.new.some_method # triggers callback
|
210
|
-
```
|
211
225
|
|
212
226
|
### Removing callbacks
|
213
227
|
|
@@ -217,7 +231,7 @@ You can remove all callbacks you added to a class by doing:
|
|
217
231
|
MyClass.remove_all_callbacks
|
218
232
|
```
|
219
233
|
|
220
|
-
Note that this not remove callbacks defined in super classes.
|
234
|
+
Note that this not remove callbacks defined in super/sub classes.
|
221
235
|
|
222
236
|
### Errors
|
223
237
|
|
@@ -225,6 +239,19 @@ There are some custom errors that after_do throws. When you try to add a callbac
|
|
225
239
|
|
226
240
|
When an error occurs during one of the callbacks that are attached to a method it will throw `AfterDo::CallbackError` with information about the original error and where the block/callback causing this error was defined to help pinpoint the error.
|
227
241
|
|
242
|
+
### How does it work?
|
243
|
+
|
244
|
+
When you attach a callback to a method with after_do what it basically does is it creates a copy of that method and then redefines the method to basically look like this (pseudo code):
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
execute_before_callbacks
|
248
|
+
return_value = original_method
|
249
|
+
execute_after_callbacks
|
250
|
+
return_value
|
251
|
+
```
|
252
|
+
|
253
|
+
To do this some helper methods are defined in the AfterDo module. As classes have to extend the AfterDo module all the methods that you are not supposed to call yourself are prefixed with `_after_do_` to minimize the risk of method name clashes. The only not prefixed method are `after`, `before` and `remove_all_callbacks`.
|
254
|
+
|
228
255
|
|
229
256
|
## Is there a before method?
|
230
257
|
|
@@ -236,12 +263,11 @@ MyClass.before :a_method do so_much end
|
|
236
263
|
|
237
264
|
Check out the [before sample](https://github.com/PragTob/after_do/blob/master/samples/before.rb).
|
238
265
|
|
239
|
-
|
240
266
|
### Method granularity
|
241
267
|
|
242
|
-
after_do works on the granularity of methods. That means that you can only attach callbacks to methods. This is no problem however, since if it's your code you can always define new methods. E.g. you want to attach callbacks to the end of some operation that happens in the middle of a method just define a new method for that piece of code.
|
268
|
+
after_do works on the granularity of methods. That means that you can only attach callbacks to methods. This is no problem however, since if it's your code you can always define new methods. E.g. if you want to attach callbacks to the end of some operation that happens in the middle of a method just define a new method for that piece of code.
|
243
269
|
|
244
|
-
I sometimes do this for evaluating
|
270
|
+
I sometimes do this for evaluating a block, as I want to do something when that block finished evaluating so I define a method `eval_block` wherein I just evaluate the block.
|
245
271
|
|
246
272
|
## Is this a good idea?
|
247
273
|
|
data/lib/after_do.rb
CHANGED
@@ -80,7 +80,7 @@ module AfterDo
|
|
80
80
|
end
|
81
81
|
|
82
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
|
83
|
+
raise NonExistingMethodError, "There is no method #{method} on #{self} to attach a block to with after_do"
|
84
84
|
end
|
85
85
|
|
86
86
|
def _after_do_aliased_name(symbol)
|
@@ -110,9 +110,9 @@ module AfterDo
|
|
110
110
|
|
111
111
|
def _after_do_execute_callback(block, method, object, *args)
|
112
112
|
begin
|
113
|
-
block.call
|
113
|
+
block.call(*args, object)
|
114
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]}
|
115
|
+
raise CallbackError, "A #{error.class}: #{error.message} was raised during an after_do callback block for method '#{method}' on the instance #{self.inspect} with the following arguments: #{args.join(', ')} defined in the file #{block.source_location[0]} in line #{block.source_location[1]}. This is the backtrace of the #{error.class}: \n #{error.backtrace.join("\n")}"
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
data/lib/after_do/version.rb
CHANGED
data/spec/after_do_spec.rb
CHANGED
@@ -125,11 +125,11 @@ describe AfterDo do
|
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'mentions the error raised' do
|
128
|
-
expect_call_back_error
|
128
|
+
expect_call_back_error(/StandardError/)
|
129
129
|
end
|
130
130
|
|
131
131
|
it 'mentions the method called' do
|
132
|
-
expect_call_back_error
|
132
|
+
expect_call_back_error(/zero/)
|
133
133
|
end
|
134
134
|
|
135
135
|
it 'mentions the file the error was raised in' do
|
@@ -137,7 +137,7 @@ describe AfterDo do
|
|
137
137
|
end
|
138
138
|
|
139
139
|
it 'mentions the original error message' do
|
140
|
-
expect_call_back_error
|
140
|
+
expect_call_back_error(/silly message/)
|
141
141
|
end
|
142
142
|
end
|
143
143
|
end
|
@@ -363,6 +363,28 @@ describe AfterDo do
|
|
363
363
|
|
364
364
|
end
|
365
365
|
end
|
366
|
+
|
367
|
+
describe 'module/class/singleton methods' do
|
368
|
+
def singleton_module
|
369
|
+
Module.new do
|
370
|
+
def self.my_singleton_method
|
371
|
+
'singleton_method'
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
it 'works when you use the singleton_class' do
|
377
|
+
my_module = singleton_module
|
378
|
+
my_module.singleton_class.extend AfterDo
|
379
|
+
my_module.singleton_class.send callback_adder, :my_singleton_method do
|
380
|
+
mockie.call
|
381
|
+
end
|
382
|
+
my_module.my_singleton_method
|
383
|
+
expect(mockie).to have_received(:call)
|
384
|
+
end
|
385
|
+
|
386
|
+
end
|
387
|
+
|
366
388
|
end
|
367
389
|
|
368
390
|
it_behaves_like 'calling callbacks', :after
|
@@ -392,4 +414,4 @@ describe AfterDo do
|
|
392
414
|
dummy_instance.zero
|
393
415
|
end
|
394
416
|
end
|
395
|
-
end
|
417
|
+
end
|
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.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Pfeiffer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-27 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
|
@@ -19,10 +19,10 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
-
- .gitignore
|
23
|
-
- .ruby-gemset
|
24
|
-
- .ruby-version
|
25
|
-
- .travis.yml
|
22
|
+
- ".gitignore"
|
23
|
+
- ".ruby-gemset"
|
24
|
+
- ".ruby-version"
|
25
|
+
- ".travis.yml"
|
26
26
|
- Gemfile
|
27
27
|
- Guardfile
|
28
28
|
- LICENSE.txt
|
@@ -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/singleton.rb
|
39
40
|
- samples/with_module.rb
|
40
41
|
- samples/within_class.rb
|
41
42
|
- spec/after_do_spec.rb
|
@@ -50,17 +51,17 @@ require_paths:
|
|
50
51
|
- lib
|
51
52
|
required_ruby_version: !ruby/object:Gem::Requirement
|
52
53
|
requirements:
|
53
|
-
- -
|
54
|
+
- - ">="
|
54
55
|
- !ruby/object:Gem::Version
|
55
56
|
version: '0'
|
56
57
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
58
|
requirements:
|
58
|
-
- -
|
59
|
+
- - ">="
|
59
60
|
- !ruby/object:Gem::Version
|
60
61
|
version: '0'
|
61
62
|
requirements: []
|
62
63
|
rubyforge_project:
|
63
|
-
rubygems_version: 2.
|
64
|
+
rubygems_version: 2.2.2
|
64
65
|
signing_key:
|
65
66
|
specification_version: 4
|
66
67
|
summary: after_do allows you to add simple after/before hooks to methods
|