namebox 0.1.9 → 0.2.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/lib/namebox.rb +77 -140
- metadata +8 -7
data/lib/namebox.rb
CHANGED
@@ -8,11 +8,8 @@
|
|
8
8
|
# This software is released "AS IS", without any warranty.
|
9
9
|
# The author is not responsible for the consequences of use of this software.
|
10
10
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# when in class methods changed by extending modules in subclasses
|
14
|
-
# (self will be the class instead of subclass when namebox is closed).
|
15
|
-
# Next versions will be only compatible with Ruby 1.9.2 or greater.
|
11
|
+
# This version is only compatible with Ruby 1.9.2 or greater.
|
12
|
+
# For use with Ruby 1.8.7 or 1.9.1, get the version 0.1.8 or 0.1.9.
|
16
13
|
|
17
14
|
class Namebox
|
18
15
|
|
@@ -21,9 +18,6 @@ class Namebox
|
|
21
18
|
map { |c| Object.const_get(c) }.
|
22
19
|
select { |m| m.is_a? Module }.uniq
|
23
20
|
|
24
|
-
### FOR RUBY 1.8.7 USE ###
|
25
|
-
CLASS_EIGENCLASS = class << Class; self; end
|
26
|
-
|
27
21
|
class << self
|
28
22
|
|
29
23
|
# Wrapper to create a namebox only to protect modules when requiring.
|
@@ -150,16 +144,12 @@ class Namebox
|
|
150
144
|
# select classes to protect against included modules
|
151
145
|
@classes = @modules.select { |m| m.is_a? Class }
|
152
146
|
|
153
|
-
#
|
154
|
-
|
155
|
-
|
156
|
-
# include eigenclasses in @classes
|
157
|
-
@classes |= @eigen_instances.keys
|
147
|
+
# get eigenclasses
|
148
|
+
eigenclasses = @classes.map { |c| class << c; self; end }
|
158
149
|
|
159
|
-
#
|
160
|
-
|
161
|
-
|
162
|
-
eigen_instances = @eigen_instances
|
150
|
+
# include eigenclasses into @classes and @modules
|
151
|
+
@classes |= eigenclasses
|
152
|
+
@modules |= eigenclasses
|
163
153
|
|
164
154
|
# save preexisting methods and included modules
|
165
155
|
inc_mods_before = get_included_modules
|
@@ -191,98 +181,14 @@ class Namebox
|
|
191
181
|
|
192
182
|
new_modules.each do |new_module|
|
193
183
|
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
protector = Module.new
|
198
|
-
|
199
|
-
# Create a module to enable a tunnel to bypass the new_module
|
200
|
-
# in super method lookup when namebox is closed to new_module.
|
184
|
+
# Get a protector module for new_module; don't recreate it
|
185
|
+
# if a protector was already created for new_module.
|
201
186
|
#
|
202
|
-
|
187
|
+
protector = protector_module(new_module)
|
203
188
|
|
204
|
-
#
|
189
|
+
# reincludes the new_module with super_tunnel
|
190
|
+
# to allow bind(self) inside protector code.
|
205
191
|
#
|
206
|
-
class << protector; self; end.send(:define_method, :to_s) do
|
207
|
-
"Protector:#{new_module}/#{klass}"
|
208
|
-
end
|
209
|
-
|
210
|
-
new_module.instance_methods.each do |method_name|
|
211
|
-
|
212
|
-
new_method = new_module.instance_method(method_name)
|
213
|
-
|
214
|
-
protector.send :define_method, method_name do |*args, &blk|
|
215
|
-
if this_nb.open?
|
216
|
-
new_method.bind(self).call(*args, &blk)
|
217
|
-
else
|
218
|
-
begin
|
219
|
-
super_tunnel.instance_method(method_name).bind(self).call(*args, &blk)
|
220
|
-
rescue NoMethodError
|
221
|
-
|
222
|
-
# Can throw error in two cases:
|
223
|
-
# 1. There's really no super method (Ruby >= 1.9)
|
224
|
-
# 2. 1.8.7 does not find super when in a module after binding.
|
225
|
-
#
|
226
|
-
raise if RUBY_VERSION >= '1.9.0'
|
227
|
-
|
228
|
-
# future method
|
229
|
-
m = nil
|
230
|
-
|
231
|
-
# search the method in old modules
|
232
|
-
old_modules.each do |old_module|
|
233
|
-
begin
|
234
|
-
m = old_module.instance_method(method_name).bind(self)
|
235
|
-
break
|
236
|
-
rescue NameError
|
237
|
-
# try next
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
unless m
|
242
|
-
|
243
|
-
# last try: superklass
|
244
|
-
begin
|
245
|
-
superklass = klass.superclass
|
246
|
-
|
247
|
-
# superklass exist?
|
248
|
-
raise NameError unless superklass
|
249
|
-
|
250
|
-
# Ruby 1.8.7 get wrong superclass for eigenclasses
|
251
|
-
if superklass == CLASS_EIGENCLASS
|
252
|
-
|
253
|
-
# Get a bound method for superclass (although self
|
254
|
-
# won't be the same: superclass instead of klass).
|
255
|
-
# Can raise NameError if method does not exist.
|
256
|
-
#
|
257
|
-
m = eigen_instances[klass].superclass.method(method_name)
|
258
|
-
|
259
|
-
else
|
260
|
-
|
261
|
-
# Try to get method; raises NameError if it doesn't exist.
|
262
|
-
m = superklass.instance_method(method_name).bind(self)
|
263
|
-
|
264
|
-
end
|
265
|
-
|
266
|
-
rescue NameError
|
267
|
-
Namebox.no_method_error(self, method_name)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
m.call(*args, &blk)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
super_tunnel.send :define_method, method_name do |*args, &blk|
|
277
|
-
super(*args, &blk)
|
278
|
-
end
|
279
|
-
|
280
|
-
end
|
281
|
-
|
282
|
-
# include super_tunnel in new_module
|
283
|
-
new_module.send :include, super_tunnel
|
284
|
-
|
285
|
-
# reincludes the new_module with super_tunnel to allow bind(self)
|
286
192
|
klass.send :include, new_module
|
287
193
|
|
288
194
|
# finally, include the protector in the class
|
@@ -299,38 +205,32 @@ class Namebox
|
|
299
205
|
|
300
206
|
# get old method
|
301
207
|
info_old = methods_before[fullname] || {}
|
302
|
-
|
303
|
-
|
208
|
+
new_method = info[:method]
|
209
|
+
old_method = info_old[:method]
|
304
210
|
|
305
211
|
# don't touch unmodified methods
|
306
|
-
next if
|
212
|
+
next if new_method == old_method
|
307
213
|
|
308
214
|
# method was modified! take some info
|
309
|
-
|
215
|
+
method_name = info[:name]
|
310
216
|
klass = info[:class]
|
311
|
-
new_bound_m = info[:bound]
|
312
|
-
old_bound_m = info_old[:bound]
|
313
217
|
|
314
218
|
# redefine the method, which will check namebox visibility dinamically
|
315
|
-
klass.send :define_method,
|
219
|
+
klass.send :define_method, method_name do |*args, &blk|
|
316
220
|
|
317
221
|
# check namebox visibility
|
318
222
|
if this_nb.open?
|
319
223
|
|
320
|
-
#
|
321
|
-
|
224
|
+
# namebox method; bind instance method to self.
|
225
|
+
new_method.bind(self).call(*args, &blk)
|
322
226
|
|
323
227
|
else
|
324
228
|
|
325
229
|
# old method or super
|
326
|
-
if
|
327
|
-
|
230
|
+
if old_method
|
231
|
+
old_method.bind(self).call(*args, &blk)
|
328
232
|
else
|
329
|
-
|
330
|
-
super(*args, &blk)
|
331
|
-
rescue NoMethodError
|
332
|
-
Namebox.no_method_error(self, m_name)
|
333
|
-
end
|
233
|
+
super(*args, &blk)
|
334
234
|
end
|
335
235
|
|
336
236
|
end
|
@@ -433,18 +333,9 @@ class Namebox
|
|
433
333
|
|
434
334
|
@modules.each do |c|
|
435
335
|
|
436
|
-
# get eigenclass
|
437
|
-
ec = class << c; self; end
|
438
|
-
|
439
336
|
c.instance_methods(false).each do |m|
|
440
337
|
fullname = "#{c}##{m}"
|
441
|
-
gm[fullname] = {:class => c, :name => m, :method => c.instance_method(m)
|
442
|
-
end
|
443
|
-
|
444
|
-
c.methods(false).each do |m|
|
445
|
-
fullname = "#{c}.#{m}"
|
446
|
-
gm[fullname] = {:class => ec, :name => m, :method => ec.instance_method(m),
|
447
|
-
:bound => c.method(m) }
|
338
|
+
gm[fullname] = {:class => c, :name => m, :method => c.instance_method(m)}
|
448
339
|
end
|
449
340
|
|
450
341
|
end
|
@@ -457,7 +348,7 @@ class Namebox
|
|
457
348
|
inc_mods = {}
|
458
349
|
|
459
350
|
@classes.each do |c|
|
460
|
-
super_c =
|
351
|
+
super_c = c.superclass
|
461
352
|
|
462
353
|
# superclass included modules must be [] even when superclass is nil
|
463
354
|
super_inc_mods = super_c && super_c.included_modules || []
|
@@ -469,14 +360,60 @@ class Namebox
|
|
469
360
|
inc_mods
|
470
361
|
end
|
471
362
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
363
|
+
def protector_module(new_module)
|
364
|
+
@protector_modules ||= {}
|
365
|
+
if @protector_modules[new_module]
|
366
|
+
@protector_modules[new_module]
|
367
|
+
else
|
368
|
+
|
369
|
+
this_nb = self
|
370
|
+
|
371
|
+
# Create a protector module to protect the changed methods.
|
372
|
+
protector = Module.new
|
373
|
+
|
374
|
+
# Create a module to enable a tunnel to bypass the new_module
|
375
|
+
# in super method lookup when namebox is closed to new_module.
|
376
|
+
#
|
377
|
+
super_tunnel = Module.new
|
378
|
+
|
379
|
+
# Give a name to protector module; useful when using Method#owner.
|
380
|
+
#
|
381
|
+
class << protector; self; end.send(:define_method, :to_s) do
|
382
|
+
"Protector:#{new_module}"
|
383
|
+
end
|
384
|
+
|
385
|
+
new_module.instance_methods.each do |method_name|
|
386
|
+
|
387
|
+
new_method = new_module.instance_method(method_name)
|
388
|
+
|
389
|
+
protector.send :define_method, method_name do |*args, &blk|
|
390
|
+
|
391
|
+
# check namebox visibility
|
392
|
+
if this_nb.open?
|
393
|
+
|
394
|
+
# namebox method; bind instance method to self.
|
395
|
+
new_method.bind(self).call(*args, &blk)
|
396
|
+
|
397
|
+
else
|
398
|
+
|
399
|
+
# super (above module thru super_tunnel); can raise NoMethodError.
|
400
|
+
super_tunnel.instance_method(method_name).bind(self).call(*args, &blk)
|
401
|
+
|
402
|
+
end
|
403
|
+
|
404
|
+
end
|
405
|
+
|
406
|
+
super_tunnel.send :define_method, method_name do |*args, &blk|
|
407
|
+
super(*args, &blk)
|
408
|
+
end
|
409
|
+
|
410
|
+
end
|
411
|
+
|
412
|
+
# include super_tunnel in new_module
|
413
|
+
new_module.send :include, super_tunnel
|
414
|
+
|
415
|
+
@protector_modules[new_module] = protector
|
478
416
|
end
|
479
|
-
s
|
480
417
|
end
|
481
418
|
|
482
419
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: namebox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -15,11 +15,12 @@ description: ! 'Create namespace boxes to protect the core classes'' methods fro
|
|
15
15
|
changes, like refinements.
|
16
16
|
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
This version is only compatible with Ruby 1.9.2 or greater. For use with Ruby 1.8.7
|
19
|
+
or 1.9.1, get the version 0.1.8 or 0.1.9.
|
20
|
+
|
21
|
+
|
22
|
+
Note: this version is under tests, and can be considered a pre-release for 1.0.0.
|
23
|
+
Please, came back soon to check for that version. ;-)'
|
23
24
|
email: sony.fermino@gmail.com
|
24
25
|
executables: []
|
25
26
|
extensions: []
|
@@ -38,7 +39,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
38
39
|
requirements:
|
39
40
|
- - ! '>='
|
40
41
|
- !ruby/object:Gem::Version
|
41
|
-
version: 1.
|
42
|
+
version: 1.9.2
|
42
43
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
44
|
none: false
|
44
45
|
requirements:
|