namebox 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|