namebox 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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.