namebox 0.0.2 → 0.0.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/lib/namebox.rb +103 -116
- metadata +4 -3
data/lib/namebox.rb
CHANGED
@@ -55,93 +55,88 @@ class Namebox
|
|
55
55
|
|
56
56
|
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
i = ba.index(ancestor)
|
62
|
-
ba[i + 1] if i
|
63
|
-
end
|
58
|
+
###################################################
|
59
|
+
# INSTANCE METHODS HELPERS
|
60
|
+
###################################################
|
64
61
|
|
65
|
-
#
|
66
|
-
#
|
62
|
+
# Get the super methods from klass' ancestors list.
|
63
|
+
# +is_instance+: boolean for instance or class methods
|
64
|
+
# +limit_ancestor+: the last ancestor to check for methods
|
65
|
+
# +default_method+: the method to return case not found
|
66
|
+
# +first+: returns the first method found; else returns an array
|
67
67
|
#
|
68
|
-
def
|
68
|
+
def super_methods(name, klass, is_instance, limit_ancestor, default_method,
|
69
|
+
first = false, &validator)
|
69
70
|
|
70
|
-
|
71
|
+
ancestors = is_instance ? klass.ancestors : class_ancestors(klass)
|
71
72
|
|
72
|
-
|
73
|
-
|
73
|
+
sm = []
|
74
|
+
limit_index = ancestors.index(limit_ancestor) || ancestors.length - 1
|
74
75
|
|
75
|
-
#
|
76
|
-
|
77
|
-
|
76
|
+
# skip first ancestor (0) - the class itself
|
77
|
+
#
|
78
|
+
for i in 1..limit_index
|
79
|
+
super_ancestor = ancestors[i]
|
80
|
+
begin
|
81
|
+
m = super_ancestor.instance_method(name)
|
82
|
+
rescue NameError
|
83
|
+
m = nil
|
84
|
+
end
|
85
|
+
|
86
|
+
# only owners (and the last) are interesting
|
87
|
+
next unless m && m.owner == super_ancestor || i == limit_index
|
88
|
+
|
89
|
+
# check if it matches the requisites
|
90
|
+
next unless validator.call(m)
|
91
|
+
|
92
|
+
return m if first
|
93
|
+
|
94
|
+
sm << m
|
78
95
|
|
79
|
-
def super_owner(name, base_class, ancestor)
|
80
|
-
begin
|
81
|
-
super_method(name, base_class, ancestor).owner
|
82
|
-
rescue NameError
|
83
96
|
end
|
97
|
+
|
98
|
+
# return found methods
|
99
|
+
return sm unless sm.empty?
|
100
|
+
|
101
|
+
# not found
|
102
|
+
first ? default_method : [default_method]
|
84
103
|
end
|
85
104
|
|
86
105
|
###################################################
|
87
106
|
# CLASS METHODS HELPERS
|
88
107
|
###################################################
|
89
108
|
|
90
|
-
# build ancestors list for class methods
|
91
|
-
def class_ancestors(
|
92
|
-
list = []
|
93
|
-
|
94
|
-
# in reverse order is easier to add modules in the correct order
|
95
|
-
# and to avoid redundancy thru Array#|
|
96
|
-
#
|
97
|
-
klass.ancestors.reverse.each do |a|
|
109
|
+
# build ancestors list for class methods lookup
|
110
|
+
def class_ancestors(c)
|
98
111
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
# add new modules to list
|
103
|
-
list |= aa.ancestors.reverse
|
104
|
-
|
105
|
-
# add current ancestor to list
|
106
|
-
list << a
|
107
|
-
end
|
112
|
+
# only classes have superclass
|
113
|
+
return c.ancestors if c.instance_of? Module
|
108
114
|
|
109
|
-
|
110
|
-
|
111
|
-
|
115
|
+
list = []
|
116
|
+
eigenclass = class << c; self; end
|
117
|
+
mod_class = eigenclass.included_modules
|
112
118
|
|
113
|
-
|
114
|
-
owner = mtd.owner
|
115
|
-
return owner if owner.instance_of? Module
|
116
|
-
ObjectSpace.each_object(owner).to_a.last
|
117
|
-
end
|
119
|
+
while c
|
118
120
|
|
119
|
-
|
120
|
-
|
121
|
-
ca = class_ancestors(base)
|
122
|
-
i = ca.index(ancestor)
|
123
|
-
ca[i + 1] if i
|
124
|
-
end
|
121
|
+
s = c.superclass
|
122
|
+
eigensuper = class << s; self; end
|
125
123
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
def class_super_method(name, base_class, ancestor = base_class)
|
124
|
+
# if there's no superclass, consider Kernel as included module;
|
125
|
+
# so it won't be added now, but later, in the correct order.
|
126
|
+
mod_super = s ? eigensuper.included_modules : [Kernel]
|
130
127
|
|
131
|
-
|
128
|
+
# add eigenclass and its included modules
|
129
|
+
# (discarding the ones inherited from superclasses)
|
130
|
+
list << eigenclass
|
131
|
+
list += mod_class - mod_super
|
132
132
|
|
133
|
-
|
134
|
-
|
133
|
+
# rotate values
|
134
|
+
c, eigenclass, mod_class = s, eigensuper, mod_super
|
135
135
|
|
136
|
-
# get the super method (can throw NameError if it doesn't exist)
|
137
|
-
super_class.method(name)
|
138
|
-
end
|
139
|
-
|
140
|
-
def class_super_owner(name, base_class, ancestor)
|
141
|
-
begin
|
142
|
-
class_owner(class_super_method(name, base_class, ancestor))
|
143
|
-
rescue NameError
|
144
136
|
end
|
137
|
+
|
138
|
+
# finally adds Class's ancestors (including Kernel)
|
139
|
+
list += Class.ancestors
|
145
140
|
end
|
146
141
|
|
147
142
|
end
|
@@ -200,6 +195,8 @@ class Namebox
|
|
200
195
|
|
201
196
|
# save preexisting methods
|
202
197
|
methods_before = get_methods
|
198
|
+
$msb = methods_before["Symbol#&"]
|
199
|
+
$mob = methods_before["Object#&"]
|
203
200
|
|
204
201
|
# ###############################################################
|
205
202
|
# RUN THE CODE, which can change the methods of protected modules
|
@@ -210,13 +207,14 @@ class Namebox
|
|
210
207
|
|
211
208
|
# get methods after changes
|
212
209
|
methods_after = get_methods
|
210
|
+
$msa = methods_after["Symbol#&"]
|
211
|
+
$moa = methods_after["Object#&"]
|
213
212
|
|
214
213
|
# compare with preexisting data to discover affected methods
|
215
214
|
unless methods_after == methods_before
|
216
215
|
|
217
216
|
# thru closure, this namebox will be useful inside redefined methods
|
218
217
|
this_nb = self
|
219
|
-
|
220
218
|
methods_after.each do |fullname, info|
|
221
219
|
|
222
220
|
# get old method
|
@@ -230,9 +228,11 @@ class Namebox
|
|
230
228
|
# method was modified! take some info
|
231
229
|
name = info[:name]
|
232
230
|
klass = info[:class]
|
231
|
+
is_instance = info[:is_instance]
|
232
|
+
old_owner = old_m && old_m.owner
|
233
233
|
|
234
234
|
# instance and class methods are managed differently
|
235
|
-
if
|
235
|
+
if is_instance
|
236
236
|
|
237
237
|
##########################################################
|
238
238
|
#
|
@@ -240,19 +240,12 @@ class Namebox
|
|
240
240
|
#
|
241
241
|
##########################################################
|
242
242
|
|
243
|
-
#
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
new_owners = []
|
248
|
-
o = new_m.owner
|
249
|
-
while o && o != old_owner
|
250
|
-
new_owners << o
|
251
|
-
o = Namebox.super_owner(name, klass, o)
|
243
|
+
# new methods to skip
|
244
|
+
new_methods = Namebox.super_methods(name, klass, is_instance,
|
245
|
+
old_owner, new_m) do |sm|
|
246
|
+
sm != old_m
|
252
247
|
end
|
253
248
|
|
254
|
-
## print "#{klass}##{name}: "; p new_owners;
|
255
|
-
|
256
249
|
# redefine the method, which will check namebox visibility dinamically
|
257
250
|
klass.send :define_method, name do |*args, &blk|
|
258
251
|
|
@@ -269,18 +262,14 @@ class Namebox
|
|
269
262
|
# must be dynamic because it can change anytime
|
270
263
|
# (someone can attach a new definition to some ancestor)
|
271
264
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
# skip new owners
|
277
|
-
while new_owners.include? m.owner
|
278
|
-
m = Namebox.super_method(name, klass, m.owner)
|
279
|
-
end
|
265
|
+
m = Namebox.super_methods(name, klass, is_instance,
|
266
|
+
old_owner, old_m, true) do |sm|
|
267
|
+
!new_methods.include?(sm)
|
268
|
+
end
|
280
269
|
|
281
|
-
|
270
|
+
unless m
|
282
271
|
|
283
|
-
# didn't find a
|
272
|
+
# didn't find a method; raise NoMethodError
|
284
273
|
|
285
274
|
# if inspect is too big, shorten it
|
286
275
|
obj = self.inspect.to_s
|
@@ -303,20 +292,13 @@ class Namebox
|
|
303
292
|
#
|
304
293
|
##########################################################
|
305
294
|
|
306
|
-
#
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
new_owners = []
|
311
|
-
o = Namebox.class_owner(new_m)
|
312
|
-
while o && o != old_owner
|
313
|
-
new_owners << o
|
314
|
-
o = Namebox.class_super_owner(name, klass, o)
|
295
|
+
# new methods to skip
|
296
|
+
new_methods = Namebox.super_methods(name, klass, is_instance,
|
297
|
+
old_owner, new_m) do |sm|
|
298
|
+
sm != old_m
|
315
299
|
end
|
316
300
|
|
317
|
-
|
318
|
-
|
319
|
-
# redefine class method thru eigenclass
|
301
|
+
# redefine the method thru eigenclass
|
320
302
|
class << klass; self; end.send :define_method, name do |*args, &blk|
|
321
303
|
|
322
304
|
# check namebox visibility
|
@@ -330,38 +312,43 @@ class Namebox
|
|
330
312
|
|
331
313
|
# search a different method to call
|
332
314
|
# must be dynamic because it can change anytime
|
333
|
-
# (someone can
|
315
|
+
# (someone can attach a new definition to some ancestor)
|
334
316
|
|
335
|
-
|
336
|
-
|
337
|
-
|
317
|
+
m = Namebox.super_methods(name, klass, is_instance,
|
318
|
+
old_owner, old_m, true) do |sm|
|
319
|
+
!new_methods.include?(sm)
|
320
|
+
end
|
338
321
|
|
339
|
-
|
340
|
-
while new_owners.include?(m_owner = Namebox.class_owner(m))
|
341
|
-
m = Namebox.class_super_method(name, klass, m_owner)
|
342
|
-
end
|
322
|
+
unless m
|
343
323
|
|
344
|
-
#
|
345
|
-
m = m.unbind.bind(self)
|
324
|
+
# didn't find a method; raise NoMethodError
|
346
325
|
|
347
|
-
|
326
|
+
# if inspect is too big, shorten it
|
327
|
+
obj = self.inspect.to_s
|
328
|
+
obj = obj[0..45] + '...' + obj[-1] if obj.length > 50
|
348
329
|
|
349
|
-
# didn't find a different method
|
350
330
|
raise NoMethodError.new("Undefined class method `#{name}' " +
|
351
|
-
"for #{
|
331
|
+
"for #{obj}:#{self.class}")
|
332
|
+
end
|
333
|
+
|
334
|
+
begin
|
335
|
+
|
336
|
+
# bind to self (raises TypeError in 1.8.7)
|
337
|
+
m = m.bind(self) if m.instance_of? UnboundMethod
|
352
338
|
|
353
339
|
rescue TypeError
|
354
340
|
|
355
341
|
# Ruby 1.8.7 does not bind singleton methods to descendant class;
|
356
|
-
# use
|
342
|
+
# try to use a pre-bound method
|
343
|
+
m = ObjectSpace.each_object(m.owner).to_a.last.method(name)
|
357
344
|
|
358
345
|
end
|
359
346
|
|
360
347
|
# run!
|
361
348
|
m.call(*args, &blk)
|
362
|
-
|
363
349
|
end
|
364
350
|
end
|
351
|
+
|
365
352
|
end
|
366
353
|
end
|
367
354
|
end
|
@@ -465,7 +452,7 @@ class Namebox
|
|
465
452
|
|
466
453
|
c.instance_methods.each do |m|
|
467
454
|
fullname = "#{c}##{m}"
|
468
|
-
gm[fullname] = {:class => c, :
|
455
|
+
gm[fullname] = {:class => c, :is_instance => true, :name => m,
|
469
456
|
:method => c.instance_method(m) }
|
470
457
|
end
|
471
458
|
|
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.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,9 +9,10 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-15 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description:
|
14
|
+
description: ! 'Please, note: this version is very unstable and it''s under tests.
|
15
|
+
Came back soon to check new versions with bug fixes.'
|
15
16
|
email: sony.fermino@gmail.com
|
16
17
|
executables: []
|
17
18
|
extensions: []
|