wrap 0.4.2 → 0.4.3
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/README +58 -0
- data/lib/wrap.rb +24 -16
- data/test/wrap_test.rb +182 -5
- data/wrap.gemspec +3 -2
- metadata +5 -4
data/README
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
NAME
|
2
|
+
wrap
|
3
|
+
|
4
|
+
SYNOPSIS
|
5
|
+
non-sucking :before and :after filers for any ruby class
|
6
|
+
|
7
|
+
DESCRIPTION
|
8
|
+
yes yes, active_support does this. but crapily. with actice_support you'll
|
9
|
+
need to do this
|
10
|
+
|
11
|
+
|
12
|
+
class Record
|
13
|
+
include ActiveSupport::Callbacks
|
14
|
+
define_callbacks :save
|
15
|
+
|
16
|
+
def save
|
17
|
+
run_callbacks :save do
|
18
|
+
puts "- save"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
but hey, if a subclass forgets to call 'super' or doesn't manually run
|
24
|
+
'run_callbacks' the codez are *screwed*. that sux. why not this?
|
25
|
+
|
26
|
+
|
27
|
+
class Record
|
28
|
+
include Wrap
|
29
|
+
|
30
|
+
wrap :save
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
yes, it's that simple. you can now do
|
35
|
+
|
36
|
+
class SubRecord < Record
|
37
|
+
before :save do
|
38
|
+
special_sauce
|
39
|
+
end
|
40
|
+
|
41
|
+
def save
|
42
|
+
no_special_sauce
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
did you get that? the :before and :after hooks will be called no matter
|
47
|
+
what the subclass does. the method will be wrapped, period. no special
|
48
|
+
work required. of course, if the sublcass messes with 'method_added' their
|
49
|
+
will be hell to pay. that's the price for simplicity.
|
50
|
+
|
51
|
+
the callbacks are very close, but not identical to active_supports. you can
|
52
|
+
return 'false' to halt the chain, but you can also simply call 'halt!'.
|
53
|
+
another neat trick is that :before callbacks will be called with the
|
54
|
+
arguments to the wrapped method itself iff possible and :after callbacks
|
55
|
+
will be called with the result of the wrapped method, iff possible.
|
56
|
+
|
57
|
+
the test suite reads pretty damn clean. have a go.
|
58
|
+
|
data/lib/wrap.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
##
|
6
6
|
#
|
7
7
|
class << Wrap
|
8
|
-
Version = '0.4.
|
8
|
+
Version = '0.4.3' unless defined?(Version)
|
9
9
|
|
10
10
|
def version
|
11
11
|
Version
|
@@ -67,11 +67,14 @@
|
|
67
67
|
end
|
68
68
|
|
69
69
|
running_callbacks(#{ name.inspect }) do
|
70
|
-
|
71
|
-
run_callbacks(:before, #{ name.inspect })
|
72
|
-
|
73
|
-
|
74
|
-
|
70
|
+
catch(:halt) do
|
71
|
+
return false unless run_callbacks(:before, #{ name.inspect }, args)
|
72
|
+
|
73
|
+
begin
|
74
|
+
result = wrapped_#{ name }(*args, &block)
|
75
|
+
ensure
|
76
|
+
run_callbacks(:after, #{ name.inspect }, [result]) unless $!
|
77
|
+
end
|
75
78
|
end
|
76
79
|
end
|
77
80
|
end
|
@@ -148,10 +151,7 @@
|
|
148
151
|
end
|
149
152
|
|
150
153
|
def initialize_callbacks!(name)
|
151
|
-
callbacks[name] ||= Map[
|
152
|
-
:before, [],
|
153
|
-
:after, []
|
154
|
-
]
|
154
|
+
callbacks[name] ||= Map[ :before, [], :after, [] ]
|
155
155
|
callbacks[name]
|
156
156
|
end
|
157
157
|
|
@@ -191,7 +191,7 @@
|
|
191
191
|
end
|
192
192
|
end
|
193
193
|
|
194
|
-
def run_callbacks(which, name)
|
194
|
+
def run_callbacks(which, name, argv)
|
195
195
|
which = which.to_s.to_sym
|
196
196
|
name = name.to_s
|
197
197
|
list = []
|
@@ -201,16 +201,24 @@
|
|
201
201
|
|
202
202
|
if ancestor.callbacks.is_a?(Map) and ancestor.callbacks[name].is_a?(Map)
|
203
203
|
callbacks = ancestor.callbacks[name][which]
|
204
|
-
|
204
|
+
accumulate = (which == :before ? :unshift : :push)
|
205
|
+
list.send(accumulate, *callbacks) if callbacks.is_a?(Array)
|
205
206
|
end
|
206
207
|
end
|
207
208
|
|
208
|
-
#p :which => list
|
209
209
|
list.each do |callback|
|
210
|
-
|
211
|
-
|
212
|
-
|
210
|
+
block = callback.respond_to?(:call) ? callback : proc{ send(callback.to_s.to_sym) }
|
211
|
+
args = argv.slice(0 .. (block.arity > 0 ? block.arity : -1))
|
212
|
+
result = instance_exec(*args, &block)
|
213
|
+
return false if result == false
|
213
214
|
end
|
215
|
+
|
216
|
+
true
|
217
|
+
end
|
218
|
+
|
219
|
+
def halt!(*args)
|
220
|
+
value = args.size == 0 ? false : args.shift
|
221
|
+
throw(:halt, value)
|
214
222
|
end
|
215
223
|
end
|
216
224
|
end
|
data/test/wrap_test.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
|
2
2
|
Testing Wrap do
|
3
3
|
|
4
|
+
##
|
5
|
+
#
|
4
6
|
testing 'that wrap can be included in a class' do
|
5
7
|
assert do
|
6
8
|
Class.new do
|
@@ -9,7 +11,25 @@ Testing Wrap do
|
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
|
-
|
14
|
+
##
|
15
|
+
#
|
16
|
+
testing 'that a method can be wrapped ***after*** it is defined' do
|
17
|
+
assert do
|
18
|
+
wrapped_class do
|
19
|
+
def foo() 42 end
|
20
|
+
|
21
|
+
assert{ new.foo() == 42 }
|
22
|
+
|
23
|
+
wrap :foo
|
24
|
+
|
25
|
+
assert{ new.foo() == 42 }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
#
|
32
|
+
testing 'that a method can be wrapped ***before*** it is defined' do
|
13
33
|
assert do
|
14
34
|
wrapped_class do
|
15
35
|
assert_raises(NoMethodError){ new.foo() }
|
@@ -21,20 +41,173 @@ Testing Wrap do
|
|
21
41
|
end
|
22
42
|
end
|
23
43
|
|
24
|
-
|
44
|
+
##
|
45
|
+
#
|
46
|
+
testing 'that wrapping gives :before and :after goodness' do
|
25
47
|
assert do
|
26
48
|
wrapped_class do
|
27
|
-
|
49
|
+
wrap :foo
|
28
50
|
|
29
|
-
|
51
|
+
define_method(:foo){ accum.push(42) }
|
52
|
+
|
53
|
+
before(:foo){ accum.push(:before) }
|
54
|
+
after(:foo){ accum.push(:after) }
|
55
|
+
|
56
|
+
assert {
|
57
|
+
c = new
|
58
|
+
c.foo()
|
59
|
+
c.accum == [:before, 42, :after]
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
30
64
|
|
65
|
+
##
|
66
|
+
#
|
67
|
+
testing 'that callbacks are halted with "false" iff they return "false"' do
|
68
|
+
assert do
|
69
|
+
wrapped_class do
|
31
70
|
wrap :foo
|
32
71
|
|
33
|
-
|
72
|
+
define_method(:foo){ accum.push(42) }
|
73
|
+
|
74
|
+
before(:foo){ accum.push(:foo) }
|
75
|
+
before(:foo){ accum.push(:bar); return false}
|
76
|
+
before(:foo){ accum.push(:foobar) }
|
77
|
+
|
78
|
+
assert {
|
79
|
+
c = new
|
80
|
+
c.foo()
|
81
|
+
c.accum == [:foo, :bar]
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
#
|
89
|
+
testing 'that callbacks can be halted with "halt!"' do
|
90
|
+
assert do
|
91
|
+
wrapped_class do
|
92
|
+
wrap :foo
|
93
|
+
|
94
|
+
define_method(:foo){ accum.push(42) }
|
95
|
+
|
96
|
+
before(:foo){ accum.push(:foo) }
|
97
|
+
before(:foo){ accum.push(:bar); halt!}
|
98
|
+
before(:foo){ accum.push(:foobar) }
|
99
|
+
|
100
|
+
assert {
|
101
|
+
c = new
|
102
|
+
c.foo()
|
103
|
+
c.accum == [:foo, :bar]
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
assert do
|
109
|
+
wrapped_class do
|
110
|
+
wrap :foo
|
111
|
+
|
112
|
+
define_method(:foo){ accum.push(42) }
|
113
|
+
|
114
|
+
after(:foo){ accum.push(:foo) }
|
115
|
+
after(:foo){ accum.push(:bar); halt!}
|
116
|
+
after(:foo){ accum.push(:foobar) }
|
117
|
+
|
118
|
+
assert {
|
119
|
+
c = new
|
120
|
+
c.foo()
|
121
|
+
c.accum == [42, :foo, :bar]
|
122
|
+
}
|
34
123
|
end
|
35
124
|
end
|
36
125
|
end
|
37
126
|
|
127
|
+
##
|
128
|
+
#
|
129
|
+
testing 'that :before callbacks are passed the number of args they can eat, and no more' do
|
130
|
+
c =
|
131
|
+
assert do
|
132
|
+
wrapped_class do
|
133
|
+
wrap :foo
|
134
|
+
|
135
|
+
define_method(:foo){|*a|}
|
136
|
+
|
137
|
+
before(:foo){|x| accum.push([x]) }
|
138
|
+
before(:foo){|x,y| accum.push([x,y]) }
|
139
|
+
before(:foo){|x,y,z| accum.push([x,y,z]) }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
assert do
|
144
|
+
o = c.new
|
145
|
+
o.foo(1,2,3)
|
146
|
+
assert o.accum === [[1], [1,2], [1,2,3]]
|
147
|
+
true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
#
|
153
|
+
testing 'that :after callbacks are passed result of the method they follow, iff possible' do
|
154
|
+
c =
|
155
|
+
assert do
|
156
|
+
wrapped_class do
|
157
|
+
wrap :foo
|
158
|
+
|
159
|
+
define_method(:foo){ result = [1,2,3] }
|
160
|
+
|
161
|
+
after(:foo){ accum.push(:nada) }
|
162
|
+
after(:foo){|result| accum.push(result) }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
assert do
|
167
|
+
o = c.new
|
168
|
+
o.foo()
|
169
|
+
assert o.accum === [:nada, [1,2,3]]
|
170
|
+
true
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
##
|
175
|
+
#
|
176
|
+
testing 'that callbacks are inherited cleverly' do
|
177
|
+
c =
|
178
|
+
assert do
|
179
|
+
wrapped_class do
|
180
|
+
wrap :foo
|
181
|
+
|
182
|
+
define_method(:foo){}
|
183
|
+
|
184
|
+
before(:foo){ accum.push(:before_superclass) }
|
185
|
+
after(:foo){ accum.push(:after_superclass) }
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
assert do
|
190
|
+
o = c.new
|
191
|
+
o.foo()
|
192
|
+
assert o.accum === [:before_superclass, :after_superclass]
|
193
|
+
end
|
194
|
+
|
195
|
+
b =
|
196
|
+
assert do
|
197
|
+
Class.new(c) do
|
198
|
+
before(:foo){ accum.push(:before_subclass) }
|
199
|
+
after(:foo){ accum.push(:after_subclass) }
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
assert do
|
204
|
+
o = b.new
|
205
|
+
o.foo()
|
206
|
+
assert o.accum === [:before_superclass, :before_subclass, :after_subclass, :after_superclass]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
|
38
211
|
private
|
39
212
|
def wrapped_class(&block)
|
40
213
|
tc = self
|
@@ -54,6 +227,10 @@ private
|
|
54
227
|
end
|
55
228
|
end
|
56
229
|
|
230
|
+
def accum
|
231
|
+
@accum ||= []
|
232
|
+
end
|
233
|
+
|
57
234
|
module_eval(&block)
|
58
235
|
end
|
59
236
|
|
data/wrap.gemspec
CHANGED
@@ -3,13 +3,14 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "wrap"
|
6
|
-
spec.version = "0.4.
|
6
|
+
spec.version = "0.4.3"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "wrap"
|
9
9
|
spec.description = "description: wrap kicks the ass"
|
10
10
|
|
11
11
|
spec.files =
|
12
|
-
["
|
12
|
+
["README",
|
13
|
+
"Rakefile",
|
13
14
|
"lib",
|
14
15
|
"lib/wrap",
|
15
16
|
"lib/wrap.rb",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: map
|
16
|
-
requirement: &
|
16
|
+
requirement: &70328097412480 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,13 +21,14 @@ dependencies:
|
|
21
21
|
version: 4.7.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70328097412480
|
25
25
|
description: ! 'description: wrap kicks the ass'
|
26
26
|
email: ara.t.howard@gmail.com
|
27
27
|
executables: []
|
28
28
|
extensions: []
|
29
29
|
extra_rdoc_files: []
|
30
30
|
files:
|
31
|
+
- README
|
31
32
|
- Rakefile
|
32
33
|
- lib/wrap.rb
|
33
34
|
- test/testing.rb
|