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.
Files changed (5) hide show
  1. data/README +58 -0
  2. data/lib/wrap.rb +24 -16
  3. data/test/wrap_test.rb +182 -5
  4. data/wrap.gemspec +3 -2
  5. 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
+
@@ -5,7 +5,7 @@
5
5
  ##
6
6
  #
7
7
  class << Wrap
8
- Version = '0.4.2' unless defined?(Version)
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
- begin
71
- run_callbacks(:before, #{ name.inspect })
72
- wrapped_#{ name }(*args, &block)
73
- ensure
74
- run_callbacks(:after, #{ name.inspect }) unless $!
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
- list.unshift(*callbacks) if callbacks.is_a?(Array)
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
- cb = callback.respond_to?(:call) ? callback : proc{ send(callback.to_s.to_sym) }
211
- #p :cb => cb
212
- instance_eval(&cb)
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
@@ -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
- testing 'that a method can be wrapped before it is defined' do
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
- testing 'that a method can be wrapped after it is defined' do
44
+ ##
45
+ #
46
+ testing 'that wrapping gives :before and :after goodness' do
25
47
  assert do
26
48
  wrapped_class do
27
- def foo() 42 end
49
+ wrap :foo
28
50
 
29
- assert{ new.foo() == 42 }
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
- assert{ new.foo() == 42 }
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
 
@@ -3,13 +3,14 @@
3
3
 
4
4
  Gem::Specification::new do |spec|
5
5
  spec.name = "wrap"
6
- spec.version = "0.4.2"
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
- ["Rakefile",
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.2
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-27 00:00:00.000000000 Z
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: &70233826961320 !ruby/object:Gem::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: *70233826961320
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