70
70
# Ruby
71
71
# nil
72
72
#
73
- # Forwardable can be used to setup delegation at the object level as well.
73
+ # SingleForwardable can be used to setup delegation at the object level as well.
74
74
#
75
75
# printer = String.new
76
+ # printer.extend SingleForwardable # prepare object for delegation
77
+ # printer.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts()
78
+ # printer.puts "Howdy!"
79
+ #
80
+ # Also, SingleForwardable can be use to Class or Module.
81
+ #
82
+ # module Facade
83
+ # extend SingleForwardable
84
+ # def_delegator :Implementation, :service
85
+ #
86
+ # class Implementation
87
+ # def service...
88
+ # end
89
+ # end
90
+ #
91
+ # If you want to use both Forwardable and SingleForwardable, you can
92
+ # use methods def_instance_delegator and def_single_delegator, etc.
93
+ #
94
+ # If the object isn't a Module and Class, You can too extend
95
+ # Forwardable module.
96
+ # printer = String.new
76
97
# printer.extend Forwardable # prepare object for delegation
77
98
# printer.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts()
78
99
# printer.puts "Howdy!"
111
132
# Also see the example at forwardable.rb.
112
133
113
134
module Forwardable
114
- FORWARDABLE_VERSION = "1.0.0"
115
-
135
+ FORWARDABLE_VERSION = "1.1.0"
136
+
137
+ @debug = nil
138
+ class <<self
139
+ attr_accessor :debug
140
+ end
141
+
116
142
# Takes a hash as its argument. The key is a symbol or an array of
117
143
# symbols. These symbols correspond to method names. The value is
118
144
# the accessor to which the methods will be delegated.
@@ -121,7 +147,7 @@ module Forwardable
121
147
# delegate method => accessor
122
148
# delegate [method, method, ...] => accessor
123
149
#
124
- def delegate ( hash )
150
+ def instance_delegate ( hash )
125
151
hash . each { |methods , accessor |
126
152
methods = methods . to_s unless methods . respond_to? ( :each )
127
153
methods . each { |method |
@@ -144,34 +170,101 @@ def delegate(hash)
144
170
def def_instance_delegators ( accessor , *methods )
145
171
methods . delete ( "__send__" )
146
172
methods . delete ( "__id__" )
147
- methods . each { | method |
173
+ for method in methods
148
174
def_instance_delegator ( accessor , method )
149
- }
175
+ end
150
176
end
151
177
152
- #
153
- # Defines a method _method_ which delegates to _obj_ (i.e. it calls
154
- # the method of the same name in _obj_). If _new_name_ is
155
- # provided, it is used as the name for the delegate method.
156
- #
157
178
def def_instance_delegator ( accessor , method , ali = method )
158
- str = %Q {
179
+ line_no = __LINE__ ; str = %{
159
180
def #{ ali } (*args, &block)
160
- #{ accessor } .send(:#{ method } , *args, &block)
181
+ begin
182
+ #{ accessor } .__send__(:#{ method } , *args, &block)
183
+ rescue Exception
184
+ $@.delete_if{|s| %r"#{ Regexp . quote ( __FILE__ ) } "o =~ s} unless Forwardable::debug
185
+ ::Kernel::raise
186
+ end
161
187
end
162
188
}
163
-
164
189
# If it's not a class or module, it's an instance
165
190
begin
166
- module_eval ( str )
191
+ module_eval ( str , __FILE__ , line_no )
167
192
rescue
168
- instance_eval ( str )
193
+ instance_eval ( str , __FILE__ , line_no )
169
194
end
195
+
170
196
end
171
197
198
+ alias delegate instance_delegate
172
199
alias def_delegators def_instance_delegators
173
200
alias def_delegator def_instance_delegator
174
201
end
175
202
176
- # compatibility
177
- SingleForwardable = Forwardable
203
+ #
204
+ # Usage of The SingleForwardable is like Fowadable module.
205
+ #
206
+ module SingleForwardable
207
+ # Takes a hash as its argument. The key is a symbol or an array of
208
+ # symbols. These symbols correspond to method names. The value is
209
+ # the accessor to which the methods will be delegated.
210
+ #
211
+ # :call-seq:
212
+ # delegate method => accessor
213
+ # delegate [method, method, ...] => accessor
214
+ #
215
+ def single_delegate ( hash )
216
+ hash . each { |methods , accessor |
217
+ methods = methods . to_s unless methods . respond_to? ( :each )
218
+ methods . each { |method |
219
+ def_single_delegator ( accessor , method )
220
+ }
221
+ }
222
+ end
223
+
224
+ #
225
+ # Shortcut for defining multiple delegator methods, but with no
226
+ # provision for using a different name. The following two code
227
+ # samples have the same effect:
228
+ #
229
+ # def_delegators :@records, :size, :<<, :map
230
+ #
231
+ # def_delegator :@records, :size
232
+ # def_delegator :@records, :<<
233
+ # def_delegator :@records, :map
234
+ #
235
+ def def_single_delegators ( accessor , *methods )
236
+ methods . delete ( "__send__" )
237
+ methods . delete ( "__id__" )
238
+ for method in methods
239
+ def_single_delegator ( accessor , method )
240
+ end
241
+ end
242
+
243
+ #
244
+ # Defines a method _method_ which delegates to _obj_ (i.e. it calls
245
+ # the method of the same name in _obj_). If _new_name_ is
246
+ # provided, it is used as the name for the delegate method.
247
+ #
248
+ def def_single_delegator ( accessor , method , ali = method )
249
+ line_no = __LINE__ ; str = %{
250
+ def #{ ali } (*args, &block)
251
+ begin
252
+ #{ accessor } .__send__(:#{ method } , *args, &block)
253
+ rescue Exception
254
+ $@.delete_if{|s| %r"#{ Regexp . quote ( __FILE__ ) } "o =~ s} unless Forwardable::debug
255
+ ::Kernel::raise
256
+ end
257
+ end
258
+ }
259
+
260
+ instance_eval ( str , __FILE__ , __LINE__ )
261
+ end
262
+
263
+ alias delegate single_delegate
264
+ alias def_delegators def_single_delegators
265
+ alias def_delegator def_single_delegator
266
+ end
267
+
268
+
269
+
270
+
0 commit comments