namebox 0.2.0 → 0.2.1

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.
Files changed (2) hide show
  1. data/lib/namebox.rb +69 -20
  2. metadata +2 -2
@@ -13,11 +13,44 @@
13
13
 
14
14
  class Namebox
15
15
 
16
- # currently loaded top-level modules
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
- # match the info
61
- m = c.match(/^(.*?):(\d+)(:in `(.*)')?$/)
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 eigenclasses of classes
170
+ # include all ancestors for modules and singleton classes of classes
131
171
  modules.each do |m|
132
172
  @modules |= m.ancestors
133
- @modules |= class << m; self; end.ancestors if m.is_a? Class
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 eigenclasses
148
- eigenclasses = @classes.map { |c| class << c; self; end }
187
+ # get singleton_classes
188
+ singleton_classes = @classes.map { |c| c.singleton_class }
149
189
 
150
- # include eigenclasses into @classes and @modules
151
- @classes |= eigenclasses
152
- @modules |= eigenclasses
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
- class << protector; self; end.send(:define_method, :to_s) do
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
- if this_nb.open?
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
- # include super_tunnel in new_module
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.0
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-20 00:00:00.000000000 Z
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.