y_support 2.0.43 → 2.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7f4a0b0a8c590f42dd23407f86cccce3ea0b95b
4
- data.tar.gz: 2cb43420440e01d7932a373aa197204f3b7115d3
3
+ metadata.gz: d09cacddac5d80bc24a3064513b05fe98bb55535
4
+ data.tar.gz: a17182ae74bb384a3c4d13abf7dc34c3a4bf5060
5
5
  SHA512:
6
- metadata.gz: 13398ec84e28cd5fdda66ccd6b040f403129a74ddc88cb3b91a264117e08a0469cba1e0006cc5d03c541e697fb17b60c41248fb711b26a9ab0a240a21c08467b
7
- data.tar.gz: 5e3031f03fd0de7d043ace4d4b7e5c7a1f1a04ae042f6869c14bfa1e67776035efe804dd9ade11c999f441bf10c2f1a6856ca8b610f44509d4fcc257c3238a98
6
+ metadata.gz: 148b04b34ba5dc66cb8d09543ae78c8558203fd8107844c0958a06e609c9dced068bbbce52052a1a66040dafa199e6a6d8f95269f6fb3fc8402a5151d4500dba
7
+ data.tar.gz: bb923dc9a8b48d19bd89705e104f63251078c5e78800bbaac7b58dc182b1000e6514d3241f57b077963038af8f1b0daae2f8fd5cc454dfd55e0839cbf308688e
@@ -4,30 +4,168 @@ module NameMagic::ClassMethods
4
4
  # Presents the instances registered by the namespace. Takes one optional
5
5
  # argument. If set to _false_, the method returns all the instances
6
6
  # registered by the namespace. If set to _true_ (default), only returns
7
- # those instances registered by the namespace, which are of the exact same
8
- # class as the method's receiver. Example:
9
- #
10
- # class Animal; include NameMagic end
11
- # Cat, Dog = Class.new( Animal ), Class.new( Animal )
12
- # Spot = Dog.new
13
- # Livia = Cat.new
14
- # Animal.instances #=> returns 2 instances
15
- # Dog.instances #=> returns 1 instance
16
- # Dog.instances( false ) #=> returns 2 instances of the namespace Animal
7
+ # those instances registered by the namespace, which are of exactly the same
8
+ # class as the receiver. Example:
9
+ #
10
+ # <code>
11
+ # class Animal; include NameMagic end
12
+ # Cat, Dog = Class.new( Animal ), Class.new( Animal )
13
+ # Spot = Dog.new
14
+ # Livia = Cat.new
15
+ # Animal.instances #=> returns 2 instances (2 animals)
16
+ # Dog.instances #=> returns 1 instance (only 1 is of Dog subclass)
17
+ # Dog.instances( false ) #=> 2 instances again (all the animals)
18
+ # </code>
17
19
  #
18
- def instances option=false
19
- const_magic
20
- return __instances__.keys if option
21
- __instances__.keys.select { |i| i.kind_of? self }
20
+ def instances option=true
21
+ return super if namespace == self
22
+ ii = namespace.instances
23
+ option ? ii.select { |i| i.kind_of? self } : ii
22
24
  end
23
25
 
24
26
  # Presents the instance names. Takes one optional argument, same as
25
- # #instances method. Unnamed instances are completely disregarded.
27
+ # +#instances+ method.
26
28
  #
27
- def instance_names option=false
29
+ def instance_names option=true
28
30
  instances( option ).names( false )
29
31
  end
30
32
 
33
+ # Presents namespace-owned +@instances+ hash. The hash consists of pairs
34
+ # <code>{ instance => instance_name }</code>. Unnamed instances have +nil+
35
+ # assigned to them as their name. (The method does not trigger
36
+ # +#const_magic+.)
37
+ #
38
+ def __instances__
39
+ return super if namespace == self
40
+ namespace.__instances__
41
+ end
42
+
43
+ # Presents namespace-owned +@avid_instances+ (array of avid instances). "Avid"
44
+ # means that the instance is able to overwrite a name used by another
45
+ # registered instance. (This method does not trigger +#const_magic+.)
46
+ #
47
+ def __avid_instances__
48
+ return super if namespace == self
49
+ namespace.__avid_instances__
50
+ end
51
+
52
+ # Returns the instance identified by the first argument, which can typically
53
+ # be a name (string/symbol). If a registered instance is supplied, it is
54
+ # returned without change. The second argument is optional, with the same
55
+ # meaning as in +NameMagic::ClassMethods#instances+ method.
56
+ #
57
+ def instance id, option=true
58
+ return super if namespace == self
59
+ namespace.instance( id ).tap { |inst|
60
+ fail NameError, "No #{self} instance #{id} registered in " +
61
+ "#{namespace}!" unless inst.kind_of? self if option
62
+ }
63
+ end
64
+
65
+ # Searches all the modules in the the object space for constants containing
66
+ # receiver class objects, and names the found instances accordingly. The
67
+ # number of the remaining nameless instances is returned.
68
+ #
69
+ def const_magic
70
+ puts "#{self}#const_magic invoked!" if ::NameMagic::DEBUG
71
+ return super if namespace == self
72
+ puts "self is not namespace, #const_magic delegated to #{namespace}" if ::NameMagic::DEBUG
73
+ namespace.const_magic
74
+ end
75
+
76
+ # Returns the nameless instances. The optional argument has the same meaning
77
+ # as in +NameMagic::ClassMethods#instances+ method.
78
+ #
79
+ def nameless_instances option=true
80
+ return super if namespace == self
81
+ ii = namespace.nameless_instances
82
+ option ? ii.select { |i| i.kind_of? self } : ii
83
+ end
84
+
85
+ # Clears namespace-owned references to a specified instance. (This is
86
+ # different from "unnaming" an instance by setting <code>inst.name =
87
+ # nil</code>, which makes the instance anonymous, but still registered.)
88
+ #
89
+ def forget instance_identifier, option=true
90
+ if namespace == self || ! option then super else
91
+ namespace.forget instance( instance_identifier )
92
+ end
93
+ end
94
+
95
+ # Clears namespace-owned references to an instance, without performing
96
+ # #const_magic first. The argument should be a registered instance. Returns
97
+ # the instance name, or _false_, if there was no such registered instance.
98
+ #
99
+ def __forget__( instance, option=true )
100
+ return super if namespace == self
101
+ fail NameError, "Supplied argument not an instance of #{self}!" unless
102
+ instance.is_a? self if option
103
+ namespace.__forget__ instance
104
+ end
105
+
106
+ # Clears namespace-owned references to all the anonymous instances.
107
+ #
108
+ def forget_nameless_instances
109
+ return super if namespace == self
110
+ namespace.forget_nameless_instances
111
+ end
112
+
113
+ # Clears namespace-owned references to all the instances.
114
+ #
115
+ def forget_all_instances
116
+ return super if namespace == self
117
+ namespace.forget_all_instances
118
+ end
119
+
120
+ # Registers a hook to execute upon instantiation. Expects a unary block, whose
121
+ # argument represents the new instance. It is called right after instantiation,
122
+ # but before naming the instance.
123
+ #
124
+ def new_instance_hook &block
125
+ return super if namespace == self
126
+ namespace.new_instance_hook &block
127
+ end
128
+
129
+ # Registers a hook to execute upon instance naming. Expects a ternary block,
130
+ # with arguments instance, name, old_name, representing respectively the
131
+ # instance to be named, the requested name, and the previous name of that
132
+ # instance (if any). The output of the block should be the name to actually
133
+ # be used. In other words, the hook can be used (among other things) to check
134
+ # and/or modify the requested name when christening the instance. It is the
135
+ # responsibility of this block to output a symbol that can be used as a Ruby
136
+ # constant name.
137
+ #
138
+ def name_set_hook &block
139
+ return super if namespace == self
140
+ namespace.name_set_hook &block
141
+ end
142
+
143
+ # Registers a hook to execute whenever the instance is asked its name. The
144
+ # instance names are objects that are kept in a hash referred to by
145
+ # +@instances+ variable owned by the namespace. Normally, +NameMagic#name+
146
+ # simply returns the name of the instance, as found in the +@instances+ hash.
147
+ # When +name_get_hook+ is defined, this name is transformed by it before being
148
+ # returned.
149
+ #
150
+ def name_get_hook &block
151
+ return super if namespace == self
152
+ namespace.name_get_hook &block
153
+ end
154
+
155
+ # Sets the namespace of the class.
156
+ #
157
+ def namespace= modul
158
+ puts "Assigning #{modul} as the namespace of #{self}." if ::NameMagic::DEBUG
159
+ modul.extend ::NameMagic::NamespaceMethods
160
+ define_singleton_method :namespace do modul end
161
+ end
162
+
163
+ # Sets the namespace for the class to self.
164
+ #
165
+ def namespace!
166
+ nil.tap { self.namespace = self }
167
+ end
168
+
31
169
  # In addition the ability to name objects upon constant assignment, as common
32
170
  # with eg. Class instances, NameMagic redefines class method #new so that it
33
171
  # swallows the named argument :name (alias :ɴ), and takes care of naming the
@@ -36,23 +174,21 @@ module NameMagic::ClassMethods
36
174
  # another object) if set to _true_.
37
175
  #
38
176
  def new *args, &block
39
- oo = args[-1].is_a?( Hash ) ? args.pop : {} # extract hash
40
- nm = if oo[:name] then oo.delete :name # consume :name if supplied
41
- elsif oo[:ɴ] then oo.delete :ɴ # consume :ɴ if supplied
42
- else nil end
43
- avid = oo[:name_avid] ? oo.delete( :name_avid ) : false # => true/false
177
+ oo = if args[-1].is_a? Hash then args.pop else {} end # extract hash
178
+ nm = oo.delete( :name ) || oo.delete( :ɴ ) # consume :name / :ɴ if given
179
+ avid = !!oo.delete( :name_avid )
44
180
  # Avoid overwriting existing names unless avid:
45
181
  fail NameError, "#{self} instance #{nm} already exists!" if
46
182
  __instances__.keys.include? nm unless avid
47
183
  args << oo unless oo.empty? # prepare the arguments
48
- new_before_name_magic( *args, &block ).tap do |new_inst| # instantiate
49
- __instances__.update new_inst => nil # Instance is created unnamed...
50
- namespace.new_instance_closure.tap { |λ|
51
- λ.( new_inst ) if λ
52
- if nm then # name has been supplied, we can name the instance:
53
- avid ? new_inst.name!( nm ) : new_inst.name = nm
54
- else # name hasn't been supplied, making the instance avid:
55
- __avid_instances__ << new_inst
184
+ super( *args, &block ).tap do |inst| # instantiate
185
+ __instances__.update( inst => nil ) # Instances are created unnamed...
186
+ namespace.new_instance_hook.tap { |λ|
187
+ λ.( inst ) if λ
188
+ if nm then # Name supplied, name the instance.
189
+ avid ? inst.name!( nm ) : inst.name = nm
190
+ else # Name not supplied, make the instance avid.
191
+ __avid_instances__ << inst
56
192
  end
57
193
  }
58
194
  end
@@ -65,4 +201,20 @@ module NameMagic::ClassMethods
65
201
  oo = args[-1].is_a?( Hash ) ? args.pop : {} # extract options
66
202
  new *args, oo.update( name_avid: true ), &block
67
203
  end
204
+
205
+ private
206
+
207
+ # Checks all the constants in some module's namespace, recursively.
208
+ #
209
+ def serve_all_modules
210
+ return super if namespace == self
211
+ namespace.serve_all_modules
212
+ end
213
+
214
+ # Performs general name validation.
215
+ #
216
+ def validate_name name
217
+ return super if namespace == self
218
+ namespace.validate_name name
219
+ end
68
220
  end # module NameMagic::ClassMethods
@@ -1,4 +1,4 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
2
 
3
3
  class Hash
4
4
  # Maps a hash into a hash, whose keys have been replaced with names of the
@@ -1,76 +1,52 @@
1
- # -*- coding: utf-8 -*-
1
+ # encoding: utf-8
2
2
 
3
3
  module NameMagic
4
4
  module NamespaceMethods
5
- # Presents class-owned namespace. By default, this is the class itself, but
6
- # may be overriden to use some other module as a namespace.
7
- #
8
- def namespace
9
- self
10
- end
11
-
12
- # Sets the namespace of the class.
13
- #
14
- def namespace= modul
15
- modul.extend ::NameMagic::NamespaceMethods unless modul == self
16
- tap { define_singleton_method :namespace do modul end }
17
- end
18
-
19
- # Makes the class/module its own namespace. This is useful especially to tell
20
- # the subclasses of a class using NameMagic to maintain their own namespaces.
21
- #
22
- def namespace!
23
- nil.tap { self.namespace = self }
24
- end
25
-
26
- # Presents the instances registered by the namespace.
5
+ # Presents the instances registered in this namespace.
27
6
  #
28
- def instances
7
+ def instances *args
29
8
  const_magic
30
9
  __instances__.keys
31
10
  end
32
11
 
33
- # Presents the instance names. Takes one optional argument, same as
34
- # #instances method. Unnamed instances are completely disregarded.
12
+ # Presents the instance names registered in this namespace.
35
13
  #
36
- def instance_names
14
+ def instance_names *args
37
15
  instances.names( false )
38
16
  end
39
17
 
40
- # Presents namespace-owned @instances hash of pairs <code>{ instance =>
41
- # instance_name }</code>. Unnamed instances have nil value. (Also, this
42
- # method does not trigger #const_magic.)
18
+ # Presents namespace-owned +@instances+ hash. The hash consists of pairs
19
+ # <code>{ instance => instance_name }</code>. Unnamed instances have +nil+
20
+ # assigned to them as their name. (The method does not trigger
21
+ # +#const_magic+.)
43
22
  #
44
- def __instances__
45
- namespace.instance_variable_get( :@instances ) ||
46
- namespace.instance_variable_set( :@instances, {} )
23
+ def __instances__ *args
24
+ @instances ||= {}
47
25
  end
48
26
 
49
- # Presents namespace-owned @avid_instances array of avid instances. "Avid"
50
- # means that the instance is able to overwrite a name used by another
51
- # registered instance. (Also, this method does not trigger const_magic).
27
+ # Avid instances registered in this namespace. ("Avid" means that the
28
+ # instance is able to steal (overwrite) a name from another registered
29
+ # instance. (The method does not trigger +#const_magic+.)
52
30
  #
53
- def __avid_instances__
54
- namespace.instance_variable_get( :@avid_instances ) ||
55
- namespace.instance_variable_set( :@avid_instances, [] )
31
+ def __avid_instances__ *args
32
+ @avid_instances ||= []
56
33
  end
57
34
 
58
- # Returns the instance identified by the argument. NameError is raised, if
59
- # the argument does not identify an instance. (It can be an instance name
60
- # (string/symbol), or an instance itself, in which case, it is just returned
61
- # back without changes.)
35
+ # Returns the instance identified by the argument, which can be typically
36
+ # a name (string/symbol). If a registered instance is supplied, it will be
37
+ # returned unchanged.
62
38
  #
63
- def instance identifier
64
- puts "#instance( #{identifier} )" if DEBUG
39
+ def instance id, *args
40
+ # puts "#instance( #{identifier} )" if DEBUG
65
41
  # In @instances hash, value 'nil' indicates a nameless instance!
66
- fail TypeError, "'nil' is not an instance identifier!" if identifier.nil?
42
+ fail TypeError, "'nil' is not an instance identifier!" if id.nil?
67
43
  ii = instances
68
- return identifier if ii.include? identifier # return the instance back
44
+ return id if ii.include? id # return the instance back
69
45
  begin # identifier not a registered instace -- treat it as a name
70
- ary = [identifier, identifier.to_sym]
71
- ii.find do |i| ary.include? i.name end
46
+ ary = [id, id.to_sym]
47
+ ii.find { |inst| ary.include? inst.name }
72
48
  rescue NoMethodError
73
- end or raise NameError, "No instance #{identifier} in #{self}."
49
+ end or fail NameError, "No instance #{id} in #{self}."
74
50
  end
75
51
 
76
52
  # Searches all the modules in the the object space for constants containing
@@ -78,24 +54,23 @@ module NameMagic
78
54
  # number of the remaining nameless instances is returned.
79
55
  #
80
56
  def const_magic
57
+ puts "#{self}#const_magic invoked!" if ::NameMagic::DEBUG
81
58
  return 0 if nameless_instances.size == 0
82
59
  serve_all_modules
83
60
  return nameless_instances.size
84
- end # def const_magic
85
-
61
+ end
62
+
86
63
  # Returns those instances, which are nameless (whose name is set to nil).
87
64
  #
88
- def nameless_instances
65
+ def nameless_instances *args
89
66
  __instances__.select { |key, val| val.nil? }.keys
90
67
  end
91
- alias unnamed_instances nameless_instances
92
- alias anonymous_instances nameless_instances
93
68
 
94
69
  # Clears namespace-owned references to a specified instance. (This is
95
70
  # different from "unnaming" an instance by setting <code>inst.name =
96
71
  # nil</code>, which makes the instance anonymous, but still registered.)
97
72
  #
98
- def forget( instance_identifier )
73
+ def forget instance_identifier, *args
99
74
  inst = begin
100
75
  instance( instance_identifier )
101
76
  rescue ArgumentError
@@ -112,7 +87,7 @@ module NameMagic
112
87
  # #const_magic first. The argument should be a registered instance. Returns
113
88
  # the instance name, or _false_, if there was no such registered instance.
114
89
  #
115
- def __forget__( instance )
90
+ def __forget__( instance, *args )
116
91
  return false unless __instances__.keys.include? instance
117
92
  namespace.send :remove_const, instance.name if instance.name
118
93
  __avid_instances__.delete( instance )
@@ -127,8 +102,6 @@ module NameMagic
127
102
  __avid_instances__.delete inst # also from here
128
103
  }
129
104
  end
130
- alias forget_unnamed_instances forget_nameless_instances
131
- alias forget_anonymous_instances forget_nameless_instances
132
105
 
133
106
  # Clears namespace-owned references to all the instances.
134
107
  #
@@ -139,48 +112,50 @@ module NameMagic
139
112
  }
140
113
  end
141
114
 
142
- # Registers a hook to execute whenever name magic creates a new instance of
143
- # the class including NameMagic. The block should take one argument (the new
144
- # instance that was created) and is called in #new method right after
145
- # instantiation, but before naming.
115
+ # Registers a hook to execute upon instantiation. Expects a unary block, whose
116
+ # argument represents the new instance. It is called right after instantiation,
117
+ # but before naming the instance.
146
118
  #
147
- def new_instance_closure &block
148
- namespace.new_instance_closure &block unless namespace == self
149
- @new_instance_closure = block if block
150
- @new_instance_closure ||= -> instance { instance }
151
- end
152
- alias new_instance_hook new_instance_closure
153
-
154
- # Registers a hook to execute whenever name setting is performed on an
155
- # instance. The block should take three arguments (instance, name, old_name).
156
- # The output value of the block is the name to be actually used the hook
157
- # thus allows to define transformations on the name when naming. It is the
158
- # responsibility of the block to output a suitable symbol (capitalized,
159
- # usable as a constant name etc.)
119
+ def new_instance_hook &block
120
+ @new_instance_hook = block if block
121
+ @new_instance_hook ||= -> instance { instance }
122
+ end
123
+
124
+ # Registers a hook to execute upon instance naming. Expects a ternary block,
125
+ # with arguments instance, name, old_name, representing respectively the
126
+ # instance to be named, the requested name, and the previous name of that
127
+ # instance (if any). The output of the block should be the name to actually
128
+ # be used. In other words, the hook can be used (among other things) to check
129
+ # and/or modify the requested name when christening the instance. It is the
130
+ # responsibility of this block to output a symbol that can be used as a Ruby
131
+ # constant name.
160
132
  #
161
- def name_set_closure &block
162
- namespace.name_set_closure &block unless namespace == self
163
- @name_set_closure = block if block
164
- @name_set_closure ||= -> name, instance, old_name=nil { name }
133
+ def name_set_hook &block
134
+ @name_set_hook = block if block
135
+ @name_set_hook ||= -> name, instance, old_name=nil { name }
165
136
  end
166
- alias name_set_hook name_set_closure
167
137
 
168
- # Registers a hook to execute whenever the instance is asked about its
169
- # name. The name object contained in __instances__[self] is subjected
170
- # to the name_get_closure before being returned as instance name.
138
+ # Registers a hook to execute whenever the instance is asked its name. The
139
+ # instance names are objects that are kept in a hash referred to by
140
+ # +@instances+ variable owned by the namespace. Normally, +NameMagic#name+
141
+ # simply returns the name of the instance, as found in the +@instances+ hash.
142
+ # When +name_get_hook+ is defined, this name is transformed by it before being
143
+ # returned.
171
144
  #
172
- def name_get_closure &block
173
- namespace.name_get_closure &block unless namespace == self
174
- @name_get_closure = block if block
175
- @name_get_closure ||= -> name { name }
145
+ def name_get_hook &block
146
+ @name_get_hook = block if block
147
+ @name_get_hook ||= -> name { name }
176
148
  end
177
- alias name_get_hook name_get_closure
178
149
 
179
150
  private
180
151
 
181
152
  # Checks all the constants in some module's namespace, recursively.
182
153
  #
183
154
  def serve_all_modules
155
+ if DEBUG then
156
+ puts "#{self}#serve_all_modules invoked!"
157
+ if name.nil? then puts "(ancestors: #{ancestors.take( 4 ).join ', '}" end
158
+ end
184
159
  todo = ( nameless_instances + __avid_instances__ ).map( &:object_id ).uniq
185
160
  ObjectSpace.each_object Module do |ɱ|
186
161
  ɱ.constants( false ).each do |const_ß|
@@ -189,21 +164,19 @@ module NameMagic
189
164
  rescue LoadError, StandardError; next end
190
165
  next unless todo.include? ◉.object_id
191
166
  puts "NameMagic: Anonymous object under #{const_ß}!" if DEBUG
192
- if __avid_instances__.map( &:object_id ).include? ◉.object_id # avid
193
- puts "NameMagic: It is avid." if DEBUG
194
- __avid_instances__ # 1. remove from avid list
195
- .delete_if { |inst| inst.object_id == ◉.object_id }
196
- ◉.name! const_ß # 2. name rudely
197
- else puts "NameMagic: It is not avid." if DEBUG # not avid
198
- ɴ = validate_name( name_set_closure.( const_ß, ◉, nil ) ).to_sym
167
+ if ◉.avid? then puts "NameMagic: It is avid." if DEBUG
168
+ ◉.make_not_avid! # 1. Remove it from the list of avid instances.
169
+ ◉.name! const_ß # 2. Name it rudely.
170
+ else puts "NameMagic: It is not avid." if DEBUG
171
+ ɴ = validate_name( name_set_hook.( const_ß, ◉, nil ) ).to_sym
199
172
  puts "NameMagic: Name adjusted to #{ɴ}." if DEBUG
200
- conflicter = begin; namespace.const_get( ɴ ); rescue NameError; end
173
+ conflicter = begin; const_get( ɴ ); rescue NameError; end
201
174
  if conflicter then
202
175
  msg = "Another #{self}-registered instance named '#{ɴ}' exists!"
203
176
  fail NameError, msg unless conflicter == ◉
204
177
  else # add the instance to the namespace
205
178
  __instances__.update( ◉ => ɴ )
206
- namespace.const_set( ɴ, ◉ )
179
+ const_set( ɴ, ◉ )
207
180
  end
208
181
  end
209
182
  todo.delete ◉.object_id # remove the id from todo list
@@ -71,25 +71,22 @@ require_relative 'name_magic/class_methods'
71
71
  module NameMagic
72
72
  DEBUG = false
73
73
 
74
- def self.included modul
75
- if modul.is_a? Class then # decorate #new
76
- class << modul
77
- alias :new_before_name_magic :new
78
- end
79
- modul.extend NameMagic::NamespaceMethods
80
- modul.extend NameMagic::ClassMethods
81
- # Attach namespace methods also to the namespace, if given
82
- begin
83
- if modul.namespace == modul then
84
- modul.define_singleton_method :namespace do modul end
85
- else
86
- modul.namespace.extend NameMagic::NamespaceMethods
74
+ def self.included target
75
+ if target.is_a? Class then # decorate #new
76
+ class << target
77
+ # Primer that sets the namespace of the class to self if the user has
78
+ # not defined otherwise when this method is first called.
79
+ #
80
+ def namespace
81
+ extend ::NameMagic::NamespaceMethods
82
+ define_singleton_method :namespace do self end # redefines itself
83
+ namespace
87
84
  end
88
- rescue NoMethodError
89
85
  end
86
+ target.singleton_class.class_exec { prepend NameMagic::ClassMethods }
90
87
  else # it is a Module -- infect it with this #include
91
- orig, this = modul.method( :included ), method( :included )
92
- modul.define_singleton_method :included do |m| this.( m ); orig.( m ) end
88
+ orig, this = target.method( :included ), method( :included )
89
+ target.define_singleton_method :included do |m| this.( m ); orig.( m ) end
93
90
  end
94
91
  end # self.included
95
92
 
@@ -111,24 +108,24 @@ module NameMagic
111
108
  #
112
109
  def __name__
113
110
  ɴ = self.class.__instances__[ self ]
114
- namespace.name_get_closure.( ɴ ) if ɴ
111
+ namespace.name_get_hook.( ɴ ) if ɴ
115
112
  end
116
113
 
117
114
  # Names an instance, cautiously (ie. no overwriting of existing names).
118
115
  #
119
116
  def name=( ɴ )
120
117
  old_ɴ = namespace.__instances__[ self ] # previous name
121
- if ɴ then puts "NameMagic: Naming with argument #{ɴ}." if DEBUG
122
- ɴ = namespace.send( :validate_name, # honor the hook
123
- namespace.name_set_closure.( ɴ, self, old_ɴ ) ).to_sym
124
- puts "NameMagic: Name adjusted to #{ɴ}." if DEBUG
118
+ if ɴ then # puts "NameMagic: Naming with argument #{ɴ}." if DEBUG
119
+ ɴ = namespace.send( :validate_name, # honor the hook
120
+ namespace.name_set_hook.( ɴ, self, old_ɴ ) ).to_sym
121
+ # puts "NameMagic: Name adjusted to #{ɴ}." if DEBUG
125
122
  return if old_ɴ == ɴ # already named as required
126
123
  fail NameError, "Name '#{ɴ}' already exists in #{namespace} namespace!" if
127
124
  self.class.__instances__.rassoc( ɴ )
128
125
  namespace.const_set ɴ, self # write a constant
129
126
  namespace.__instances__[ self ] = ɴ # write to @instances
130
127
  namespace.__forget__ old_ɴ # forget the old name of self
131
- else puts "NameMagic: Unnaming #{old_ɴ || self}" if DEBUG
128
+ else # puts "NameMagic: Unnaming #{old_ɴ || self}" if DEBUG
132
129
  namespace.__instances__.update( self => nil ) # unname in @instances
133
130
  namespace.send :remove_const, old_ɴ if old_ɴ # remove namespace const.
134
131
  end
@@ -138,10 +135,10 @@ module NameMagic
138
135
  #
139
136
  def name!( ɴ )
140
137
  old_ɴ = namespace.__instances__[ self ] # previous name
141
- if ɴ then puts "NameMagic: Rudely naming with #{ɴ}." if DEBUG
138
+ if ɴ then # puts "NameMagic: Rudely naming with #{ɴ}." if DEBUG
142
139
  ɴ = namespace.send( :validate_name, # honor the hook
143
- namespace.name_set_closure.( ɴ, self, old_ɴ ) ).to_sym
144
- puts "NameMagic: Name adjusted to #{ɴ}." if DEBUG
140
+ namespace.name_set_hook.( ɴ, self, old_ɴ ) ).to_sym
141
+ # puts "NameMagic: Name adjusted to #{ɴ}." if DEBUG
145
142
  return false if old_ɴ == ɴ # already named as required
146
143
  pair = namespace.__instances__.rassoc( ɴ )
147
144
  namespace.__forget__( pair[0] ) if pair # rudely forget the collider
@@ -152,4 +149,16 @@ module NameMagic
152
149
  self.name = nil # unnaming, no collider issues
153
150
  end
154
151
  end
152
+
153
+ # Is the instance avid for a name? (Will it overwrite other instance names?)
154
+ #
155
+ def avid?
156
+ namespace.__avid_instances__.any? &method( :equal? )
157
+ end
158
+
159
+ # Make the instance not avid.
160
+ #
161
+ def make_not_avid!
162
+ namespace.__avid_instances__.delete_if { |i| i.object_id == object_id }
163
+ end
155
164
  end # module NameMagic
@@ -1,4 +1,4 @@
1
1
  module YSupport
2
- VERSION = "2.0.43"
2
+ VERSION = "2.1.0"
3
3
  DEBUG = false
4
4
  end
@@ -11,18 +11,20 @@ describe NameMagic do
11
11
  @reporter = Object.new
12
12
  puts "..."
13
13
  @reporter.singleton_class.class_exec { attr_reader :report, :naming }
14
- @ç.namespace.new_instance_closure do |instance|
14
+ @ç.ancestors.must_include NameMagic
15
+ @ç.singleton_class.ancestors.must_include NameMagic::ClassMethods
16
+ @ç.namespace.new_instance_hook do |instance|
15
17
  @reporter.define_singleton_method :report do "Instance reported" end
16
18
  end
17
- @ç.namespace.name_set_closure do |name, instance, old_name|
19
+ @ç.namespace.name_set_hook do |name, instance, old_name|
18
20
  @reporter.define_singleton_method :name_set do
19
21
  "Name of the new instance was #{name}"
20
22
  end
21
23
  name
22
24
  end
23
- @ç.name_get_closure do |name_object|
25
+ @ç.name_get_hook do |name_object|
24
26
  @reporter.define_singleton_method :name_get do
25
- "Name get closure called on #{name_object}"
27
+ "Name get hook called on #{name_object}"
26
28
  end
27
29
  name_object
28
30
  end
@@ -37,7 +39,7 @@ describe NameMagic do
37
39
  @reporter.report.must_equal "Instance reported"
38
40
  @reporter.name_set.must_equal "Name of the new instance was Boris"
39
41
  x.name.must_equal :Boris
40
- @reporter.name_get.must_equal "Name get closure called on Boris"
42
+ @reporter.name_get.must_equal "Name get hook called on Boris"
41
43
  ufo = @ç.new
42
44
  @ç.nameless_instances.must_equal [ufo]
43
45
  UFO = @ç.new
@@ -45,17 +47,21 @@ describe NameMagic do
45
47
  @reporter.name_set.must_equal "Name of the new instance was Boris"
46
48
  UFO.name
47
49
  @reporter.name_set.must_equal "Name of the new instance was UFO"
48
- @reporter.name_get.must_equal "Name get closure called on UFO"
50
+ @reporter.name_get.must_equal "Name get hook called on UFO"
49
51
  Elaine = @ç.new
50
52
  Elaine.name.must_equal :Elaine
51
53
  m = Module.new
52
54
  XXX = m
53
55
  @ç.namespace = XXX
54
56
  @ç.namespace.must_equal m
57
+ @ç.singleton_class.must_include ::NameMagic::ClassMethods
58
+ m.singleton_class.must_include ::NameMagic::NamespaceMethods
55
59
  Rover = @ç.new
60
+ @ç.namespace.must_equal XXX
61
+ @ç.nameless_instances.must_equal [ Rover ]
56
62
  @ç.const_magic
57
- XXX::Rover.must_be_kind_of @ç
58
63
  Rover.name.must_equal :Rover
64
+ XXX::Rover.must_be_kind_of @ç
59
65
  @ç.namespace!
60
66
  Spot = @ç.new
61
67
  @ç.const_magic
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: y_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.43
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - boris
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-21 00:00:00.000000000 Z
11
+ date: 2013-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport