no_backsies 0.1.0

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.rdoc ADDED
@@ -0,0 +1,56 @@
1
+ = No Backsies
2
+
3
+ == DESCRIPTION
4
+
5
+ NoBackies is a callback layer built on top of Ruby's built-in callback
6
+ methods. It makes it possible to add new callbacks very easily, without
7
+ having to fuss with more nuanced issues of defining and redefining callback
8
+ methods.
9
+
10
+
11
+ == RESOURCES
12
+
13
+ * home: http://rubyworks.github.com/nobacksies
14
+ * code: http://github.com/rubyworks/nobacksies
15
+ * mail: http://groups.google.com/group/rubyworks-mailinglist
16
+
17
+
18
+ == EXAMPLE
19
+
20
+ Here is an example take from the Anise[http://rubyworks.github.com/anise]
21
+ project.
22
+
23
+ class Y
24
+ include Anise
25
+ include NoBacksies
26
+
27
+ def self.doc(string)
28
+ callback :method_added do |method|
29
+ self.ann(method, :doc=>string)
30
+ end
31
+ end
32
+
33
+ doc "here"
34
+
35
+ def foo; end
36
+ end
37
+
38
+ Y.ann(:foo, :doc) #=> "here"
39
+
40
+
41
+ == INSTALLATION
42
+
43
+ Install the RubyGems package in the usual fahsion.
44
+
45
+ $ gem install nobacksies
46
+
47
+
48
+ == LEGAL
49
+
50
+ (Apache 2.0 License)
51
+
52
+ Copyright (c) 2011 Thomas Sawyer
53
+
54
+ Unless otherwise negotiated with the original author, NoBacksies is
55
+ distributable under the terms of the Apache 2.0 license. See the
56
+ Apache2.txt file for details.
@@ -0,0 +1,289 @@
1
+ # NoBacksies module ecapsulates all supported callback mixins.
2
+ #
3
+ # NoBackseis::Callbacks can be mixed-in and all supported callbacks will
4
+ # be applied to the class or module.
5
+ #
6
+ # class Y
7
+ # include NoBacksies::Callbacks
8
+ #
9
+ # def self.list
10
+ # @list ||= []
11
+ # end
12
+ #
13
+ # callback :method_added do |method|
14
+ # list << method
15
+ # end
16
+ #
17
+ # def foo; end
18
+ # def bar; end
19
+ # end
20
+ #
21
+ # Y.list.assert #=> [:foo, :bar]
22
+ #
23
+ # Using callbacks can easily lead to infinite loops. NoBacksies makes it
24
+ # easier to control callback expression via the #callback_express
25
+ # method.
26
+ #
27
+ # class Z
28
+ # include NoBacksies::Callbacks
29
+ #
30
+ # def self.list
31
+ # @list ||= []
32
+ # end
33
+ #
34
+ # callback :method_added do |method|
35
+ # callback_express :method_added=>false do
36
+ # define_method("#{method}!") do
37
+ # send(method) + "!"
38
+ # end
39
+ # end
40
+ # end
41
+ #
42
+ # def foo; "foo"; end
43
+ # def bar; "bar"; end
44
+ # end
45
+ #
46
+ # y = Y.new
47
+ # y.foo! #=> "foo!"
48
+ #
49
+ # NOTE: Currently the NoBackies module only supports class level callbacks.
50
+ # We will look into adding instance level callbacks in a future version.
51
+ #
52
+ #--
53
+ # TODO: What about adding `super if defined?(super)` to callback methods?
54
+ # Should this be standard? Should it occur before or after? Or should
55
+ # in be controlled via a special callback, e.g. `callback method_added, :super`?
56
+ #++
57
+
58
+ module NoBacksies
59
+
60
+ #
61
+
62
+ module Callbacks
63
+ # Apply all supported callback modules.
64
+ def self.append_features(base)
65
+ base.extend CallbackMethods
66
+ base.extend MethodAdded
67
+ base.extend MethodRemoved
68
+ base.extend MethodUndefined
69
+ base.extend SingletonMethodAdded
70
+ base.extend SingletonMethodRemoved
71
+ base.extend SingletonMethodUndefined
72
+ base.extend ConstMissing
73
+ base.extend Included
74
+ base.extend Extended
75
+ end
76
+ end
77
+
78
+ # The CallbackMethods module adds the callback methods which are used
79
+ # define and access callback definitions. Mixing-in this module is
80
+ # handled automatically, so you do not need to worry with it. In other
81
+ # words, consider the module *private*.
82
+
83
+ module CallbackMethods
84
+ # Define a callback.
85
+ def callback(name, express={}, &block)
86
+ callbacks[name.to_sym] << block
87
+ end
88
+
89
+ #
90
+ def callbacks
91
+ @_callbacks ||= (
92
+ anc = ancestors[1..-1].find do |anc|
93
+ anc.callbacks rescue nil # TODO: Need faster way!
94
+ end
95
+ anc ? anc.callbacks.dup : Hash.new{|h,k| h[k]=[]}
96
+ )
97
+ end
98
+
99
+ # Returns Hash of true/false activity state of callbacks.
100
+ #
101
+ # TODO: Should expression be inherited?
102
+ def callback_express(express={}, &block)
103
+ @_callback_express ||= Hash.new{|h,k| h[k]=true}
104
+
105
+ if block
106
+ tmp = @_callback_express.dup
107
+ express.each{ |k,v| @_callback_express[k.to_sym] = !!v }
108
+ block.call
109
+ @_callback_express = tmp
110
+ else
111
+ express.each{ |k,v| @_callback_express[k.to_sym] = !!v }
112
+ end
113
+
114
+ @_callback_express
115
+ end
116
+ end
117
+
118
+ # Callback system for #method_added.
119
+ module MethodAdded
120
+ #
121
+ def self.append_features(base)
122
+ base.extend CallbackMethods
123
+ base.extend self
124
+ end
125
+
126
+ #
127
+ def method_added(method)
128
+ return unless callback_express[:method_added]
129
+ callbacks[:method_added].each do |block|
130
+ block.call(method)
131
+ end
132
+ end
133
+ end
134
+
135
+ # Callback system for #method_removed.
136
+ module MethodRemoved
137
+ #
138
+ def self.append_features(base)
139
+ base.extend CallbackMethods
140
+ base.extend self
141
+ end
142
+
143
+ #
144
+ def method_removed(method)
145
+ return unless callback_express[:method_removed]
146
+ callbacks[:method_removed].each do |block|
147
+ block.call(method)
148
+ end
149
+ end
150
+ end
151
+
152
+ # Callback system for #method_removed.
153
+ module MethodUndefined
154
+ #
155
+ def self.append_features(base)
156
+ base.extend CallbackMethods
157
+ base.extend self
158
+ end
159
+
160
+ #
161
+ def method_undefined(method)
162
+ return unless callback_express[:method_undefined]
163
+ callbacks[:method_undefined].each do |block|
164
+ block.call(method)
165
+ end
166
+ end
167
+ end
168
+
169
+ # Callback system for #method_added.
170
+ module SingletonMethodAdded
171
+ #
172
+ def self.append_features(base)
173
+ base.extend CallbackMethods
174
+ base.extend self
175
+ end
176
+
177
+ #
178
+ def singleton_method_added(method)
179
+ return unless callback_express[:singleton_method_added]
180
+ callbacks[:singleton_method_added].each do |block|
181
+ block.call(method)
182
+ end
183
+ end
184
+ end
185
+
186
+ # Callback system for #method_removed.
187
+ module SingletonMethodRemoved
188
+ #
189
+ def self.append_features(base)
190
+ base.extend CallbackMethods
191
+ base.extend self
192
+ end
193
+
194
+ #
195
+ def singleton_method_removed(method)
196
+ return unless callback_express[:singleton_method_removed]
197
+ callbacks[:singleton_method_removed].each do |block|
198
+ block.call(method)
199
+ end
200
+ end
201
+ end
202
+
203
+ # Callback system for #method_removed.
204
+ module SingletonMethodUndefined
205
+ #
206
+ def self.append_features(base)
207
+ base.extend CallbackMethods
208
+ base.extend self
209
+ end
210
+
211
+ #
212
+ def singleton_method_undefined(method)
213
+ return unless callback_express[:singleton_method_undefined]
214
+ callbacks[:singleton_method_undefined].each do |block|
215
+ block.call(method)
216
+ end
217
+ end
218
+ end
219
+
220
+ # Callback system for #const_missing.
221
+ module ConstMissing
222
+ #
223
+ def self.append_features(base)
224
+ base.extend CallbackMethods
225
+ base.extend self
226
+ end
227
+
228
+ #
229
+ def const_missing(const)
230
+ return unless callback_express[:cont_missing]
231
+ callbacks[:const_missing].each do |block|
232
+ block.call(const)
233
+ end
234
+ end
235
+ end
236
+
237
+ # Callback system for #included.
238
+ module Included
239
+ #
240
+ def self.append_features(base)
241
+ base.extend CallbackMethods
242
+ base.extend self
243
+ end
244
+
245
+ #
246
+ def included(mod)
247
+ return unless callback_express[:included]
248
+ callbacks[:included].each do |block|
249
+ block.call(mod)
250
+ end
251
+ end
252
+ end
253
+
254
+ # Callback system for #extended.
255
+ module Extended
256
+ #
257
+ def self.append_features(base)
258
+ base.extend CallbackMethods
259
+ base.extend self
260
+ end
261
+
262
+ #
263
+ def extended(mod)
264
+ return unless callback_express[:extended]
265
+ callbacks[:extended].each do |block|
266
+ block.call(mod)
267
+ end
268
+ end
269
+ end
270
+
271
+ # Callback system for #inherited.
272
+ module Inherited
273
+ #
274
+ def self.append_features(base)
275
+ base.extend CallbackMethods
276
+ base.extend self
277
+ end
278
+
279
+ #
280
+ def extended(mod)
281
+ return unless callback_express[:inherited]
282
+ callbacks[:inherited].each do |block|
283
+ block.call(mod)
284
+ end
285
+ end
286
+ end
287
+
288
+ end
289
+
@@ -0,0 +1,28 @@
1
+ = Basic Example
2
+
3
+ First require the 'nobacksies' library.
4
+
5
+ require 'no_backsies'
6
+
7
+ Include the Callbacks module in a class and define
8
+ a callback procedure.
9
+
10
+ class Y
11
+ include NoBacksies::Callbacks
12
+
13
+ def self.list
14
+ @list ||= []
15
+ end
16
+
17
+ callback :method_added do |method|
18
+ list << method
19
+ end
20
+
21
+ def foo; end
22
+ def bar; end
23
+ end
24
+
25
+ We can see that +list+ holds the methods added.
26
+
27
+ Y.list.assert == [:foo, :bar]
28
+
@@ -0,0 +1,38 @@
1
+ = Callback Expression
2
+
3
+ NoBacksies makes it easier to control callback expression. This
4
+ is useful in the prevention of infinite recursion. For instance,
5
+ infinite recursion is a common problem when a +method_added+ callback
6
+ defines a new method.
7
+
8
+ Here is an example that demonstrates how to work around this problem
9
+ using the +callback_express+ method.
10
+
11
+ class Z
12
+ include NoBacksies::Callbacks
13
+
14
+ def self.list
15
+ @list ||= []
16
+ end
17
+
18
+ callback :method_added do |method|
19
+ callback_express :method_added=>false do
20
+ define_method("#{method}!") do
21
+ send(method) + "!"
22
+ end
23
+ end
24
+ end
25
+
26
+ def foo; "foo"; end
27
+ def bar; "bar"; end
28
+ end
29
+
30
+ In this example, a new `Z` object will get an automatically defined bang method
31
+ for every explicitly defined method.
32
+
33
+ z = Z.new
34
+ z.foo #=> "foo"
35
+ z.foo! #=> "foo!"
36
+ z.bar #=> "bar"
37
+ z.bar! #=> "bar!"
38
+
@@ -0,0 +1,2 @@
1
+ require 'no_backsies'
2
+
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: no_backsies
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Thomas Sawyer
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-04-29 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: syckle
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: qed
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ description: |-
50
+ NoBackies is a callback layer built on top of Ruby's built-in callback
51
+ methods. It makes it possible to add new callbacks very easily, without
52
+ having to fuss with more nuanced issues of defining and redefining callback
53
+ methods.
54
+ email: transfire@gmail.com
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files:
60
+ - README.rdoc
61
+ files:
62
+ - lib/no_backsies.rb
63
+ - qed/01_example.rdoc
64
+ - qed/02_express.rdoc
65
+ - qed/applique/no_backsies.rb
66
+ - README.rdoc
67
+ has_rdoc: true
68
+ homepage: http://rubyworks.github.com/nobacksies
69
+ licenses: []
70
+
71
+ post_install_message:
72
+ rdoc_options:
73
+ - --title
74
+ - NoBacksies API
75
+ - --main
76
+ - README.rdoc
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 3
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ requirements: []
98
+
99
+ rubyforge_project: no_backsies
100
+ rubygems_version: 1.3.7
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: Better handling of Ruby callbacks
104
+ test_files: []
105
+