namebox 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/namebox.rb +69 -20
- metadata +2 -2
data/lib/namebox.rb
CHANGED
@@ -13,11 +13,44 @@
|
|
13
13
|
|
14
14
|
class Namebox
|
15
15
|
|
16
|
-
#
|
16
|
+
# Currently loaded top-level modules
|
17
17
|
CORE = (Module.constants - [:Config]).
|
18
18
|
map { |c| Object.const_get(c) }.
|
19
19
|
select { |m| m.is_a? Module }.uniq
|
20
20
|
|
21
|
+
# Permits to call the previous (old) version of the method, by calling _old(...)
|
22
|
+
module Old
|
23
|
+
|
24
|
+
# Check if it's already calling old, to call old and avoid recallings.
|
25
|
+
def _calling_old? fullname
|
26
|
+
_calling_old.include? fullname
|
27
|
+
end
|
28
|
+
|
29
|
+
# Call the previous (old) version of the method.
|
30
|
+
def _old(*args, &blk)
|
31
|
+
info = Namebox.caller_to_hash(caller[0])
|
32
|
+
method_name = info[:method]
|
33
|
+
method = self.method(method_name)
|
34
|
+
owner = method.owner
|
35
|
+
fullname = "#{owner}##{method_name}"
|
36
|
+
set_calling_old fullname
|
37
|
+
r = method.call(*args, &blk)
|
38
|
+
@_calling_old.delete(fullname)
|
39
|
+
r
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# stores info whether is calling the old version
|
45
|
+
def _calling_old
|
46
|
+
@_calling_old ||= []
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_calling_old fullname
|
50
|
+
_calling_old.push fullname
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
21
54
|
class << self
|
22
55
|
|
23
56
|
# Wrapper to create a namebox only to protect modules when requiring.
|
@@ -57,12 +90,8 @@ class Namebox
|
|
57
90
|
c = cr[cr.index { |s| s.start_with? __FILE__ } - 1]
|
58
91
|
raise "Unable to find a valid caller file in #{caller.inspect}" unless c
|
59
92
|
|
60
|
-
#
|
61
|
-
|
62
|
-
raise "Unexpected caller syntax in \"#{c}\"" unless m
|
63
|
-
|
64
|
-
# label them
|
65
|
-
{:file => m[1], :line => m[2].to_i, :method => m[4]}
|
93
|
+
# convert into hash
|
94
|
+
caller_to_hash c
|
66
95
|
|
67
96
|
end
|
68
97
|
|
@@ -78,6 +107,17 @@ class Namebox
|
|
78
107
|
raise NoMethodError.new(msg)
|
79
108
|
end
|
80
109
|
|
110
|
+
def caller_to_hash a_caller
|
111
|
+
|
112
|
+
# match the info
|
113
|
+
m = a_caller.match(/^(.*?):(\d+)(:in `(.*)')?$/)
|
114
|
+
raise "Unexpected caller syntax in \"#{a_caller}\"" unless m
|
115
|
+
|
116
|
+
# label them
|
117
|
+
{:file => m[1], :line => m[2].to_i, :method => m[4]}
|
118
|
+
|
119
|
+
end
|
120
|
+
|
81
121
|
end
|
82
122
|
|
83
123
|
# +modules_to_protect+ must be the classes themselves, e.g., String, Symbol,
|
@@ -127,10 +167,10 @@ class Namebox
|
|
127
167
|
# avoid redundancy
|
128
168
|
@modules.uniq!
|
129
169
|
|
130
|
-
# include all ancestors for modules and
|
170
|
+
# include all ancestors for modules and singleton classes of classes
|
131
171
|
modules.each do |m|
|
132
172
|
@modules |= m.ancestors
|
133
|
-
@modules |=
|
173
|
+
@modules |= m.singleton_class.ancestors if m.is_a? Class
|
134
174
|
end
|
135
175
|
end
|
136
176
|
|
@@ -144,12 +184,12 @@ class Namebox
|
|
144
184
|
# select classes to protect against included modules
|
145
185
|
@classes = @modules.select { |m| m.is_a? Class }
|
146
186
|
|
147
|
-
# get
|
148
|
-
|
187
|
+
# get singleton_classes
|
188
|
+
singleton_classes = @classes.map { |c| c.singleton_class }
|
149
189
|
|
150
|
-
# include
|
151
|
-
@classes |=
|
152
|
-
@modules |=
|
190
|
+
# include singleton_classes into @classes and @modules
|
191
|
+
@classes |= singleton_classes
|
192
|
+
@modules |= singleton_classes
|
153
193
|
|
154
194
|
# save preexisting methods and included modules
|
155
195
|
inc_mods_before = get_included_modules
|
@@ -219,10 +259,10 @@ class Namebox
|
|
219
259
|
klass.send :define_method, method_name do |*args, &blk|
|
220
260
|
|
221
261
|
# check namebox visibility
|
222
|
-
if this_nb.open?
|
262
|
+
if this_nb.open? && !_calling_old?(fullname)
|
223
263
|
|
224
264
|
# namebox method; bind instance method to self.
|
225
|
-
new_method.bind(self).call(*args, &blk)
|
265
|
+
r = new_method.bind(self).call(*args, &blk)
|
226
266
|
|
227
267
|
else
|
228
268
|
|
@@ -234,7 +274,12 @@ class Namebox
|
|
234
274
|
end
|
235
275
|
|
236
276
|
end
|
277
|
+
|
237
278
|
end
|
279
|
+
|
280
|
+
# permits to call the old methods
|
281
|
+
klass.send :include, Namebox::Old
|
282
|
+
|
238
283
|
end
|
239
284
|
end
|
240
285
|
end
|
@@ -378,7 +423,7 @@ class Namebox
|
|
378
423
|
|
379
424
|
# Give a name to protector module; useful when using Method#owner.
|
380
425
|
#
|
381
|
-
|
426
|
+
protector.singleton_class.send(:define_method, :to_s) do
|
382
427
|
"Protector:#{new_module}"
|
383
428
|
end
|
384
429
|
|
@@ -389,10 +434,11 @@ class Namebox
|
|
389
434
|
protector.send :define_method, method_name do |*args, &blk|
|
390
435
|
|
391
436
|
# check namebox visibility
|
392
|
-
|
437
|
+
fullname = "#{protector}##{method_name}"
|
438
|
+
if this_nb.open? && !_calling_old?(fullname)
|
393
439
|
|
394
440
|
# namebox method; bind instance method to self.
|
395
|
-
new_method.bind(self).call(*args, &blk)
|
441
|
+
r = new_method.bind(self).call(*args, &blk)
|
396
442
|
|
397
443
|
else
|
398
444
|
|
@@ -409,7 +455,10 @@ class Namebox
|
|
409
455
|
|
410
456
|
end
|
411
457
|
|
412
|
-
#
|
458
|
+
# permits to call the old methods
|
459
|
+
new_module.send :include, Namebox::Old
|
460
|
+
|
461
|
+
# include super_tunnel in new_module (must be included after Old)
|
413
462
|
new_module.send :include, super_tunnel
|
414
463
|
|
415
464
|
@protector_modules[new_module] = protector
|
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.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-27 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'Create namespace boxes to protect the core classes'' methods from
|
15
15
|
changes, like refinements.
|