Module: NameMagic

Defined in:
lib/y_support/name_magic.rb

Overview

This mixin imitates Ruby constant magic and automates the named argument :name, alias :ɴ (Character “ɴ”, Unicode small capital N, generally stands for “name” ins YSupport). One can write:

require 'y_support/name_magic'
class Foo; include NameMagic end
Bar = Foo.new

and the resulting object will know its #name:

Bar._name_ #=> :Bar
Bar.full_name #=> "Foo::Bar"
Foo::Bar #=> <Foo:0x.....>

This is done by searching whole Ruby namespace for constants, triggered by the method #const_magic defined in the namespace mixin. (Once the object is named, subsequent constant assignments have no effects.) By default, the namespace is the class, in which NameMagic is included, but it is possible to prescribe another module as a namespace:

Quux = Module.new
class FooBar
  include NameMagic
  self.namespace = Quux
end
FooBar.new name: "Baz"
FooBar::Baz #=> NameError
Quux::Baz #=> <FooBar:0x.....>

When subclassing the classes with NameMagic included, namespace setting does not change:

class Animal; include NameMagic end
class Dog < Animal; end
class Cat < Animal; end
Dog.namespace #=> Animal
Cat.namespace #=> Animal
Livia = Cat.new
Cat.instances._names_ #=> []
Animal.instances._names_ #=> [:Livia]

To make the subclasses use each their own namespace, use #namespace! method:

Dog.namespace!

NameMagic also provides an alternative way to create named objects by taking care of :name (alias :ɴ) named argument of the constructor:

Dog.new name: "Spot"
Dog.new 

Lastly, a name can be assigned by #name= accssor, as in

o = SomeClass.new o.name = "SomeName"

Hook is provided for when the name magic is performed, as well as when the name is retrieved.

Defined Under Namespace

Modules: ClassMethods, NamespaceMethods

Constant Summary collapse

DEBUG =
false

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(target) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/y_support/name_magic.rb', line 76

def self.included target
  if target.is_a? Class then # decorate #new
    target.singleton_class.class_exec do
      # Primer that sets the namespace of the class to self if the user has
      # not defined otherwise when this method is first called.
      # 
      define_method :namespace do
        target.extend ::NameMagic::NamespaceMethods
        define_singleton_method :namespace do target end # redefines itself
        namespace
      end
    end
    target.singleton_class.class_exec { prepend ::NameMagic::ClassMethods }
  else # it is a Module -- infect it with this #include
    orig, this = target.method( :included ), method( :included )
    target.define_singleton_method :included do |m| this.( m ); orig.( m ) end
  end
end

Instance Method Details

#__name__Object

Retrieves the instance name. Does not trigger #const_magic before doing so.



124
125
126
127
# File 'lib/y_support/name_magic.rb', line 124

def __name__
  

#_name_Object Also known as: ɴ, name

Retrieves the instance’s name not prefixed by the namespace as a symbol. Underlines (#name) distinguish this method from #name method, which returns full name string for compatibility with vanilla Ruby Module#name.



105
106
107
108
# File 'lib/y_support/name_magic.rb', line 105

def _name_
  self.class.const_magic
  __name__ or ( yield self if block_given? )
end

#avid?Boolean

Is the instance avid for a name? (Will it overwrite other instance names?)

Returns:

  • (Boolean)


163
164
165
# File 'lib/y_support/name_magic.rb', line 163

def avid?
  namespace.__avid_instances__.any? &method( :equal? )
end

#full_nameObject

Returns the instance’s full name, a string in the style of those returned by Module#name method, eg. “Namespace::Name”.



116
117
118
# File 'lib/y_support/name_magic.rb', line 116

def full_name
  "#{namespace.name || namespace.inspect}::#{namespace.instances[ self ]}"
end

#inspectObject

Default #inspect method for NameMagic includers.



192
193
194
# File 'lib/y_support/name_magic.rb', line 192

def inspect
  to_s
end

#make_not_avid!Object

Make the instance not avid.



169
170
171
# File 'lib/y_support/name_magic.rb', line 169

def make_not_avid!
  namespace.__avid_instances__.delete_if { |i| i.object_id == object_id }
end

#name!(name) ⇒ Object

Names an instance, aggresively (overwrites existing names).



149
150
151
152
153
154
155
156
157
158
159
# File 'lib/y_support/name_magic.rb', line 149

def name!( name )
  old_

#name=(name) ⇒ Object

Names an instance, cautiously (ie. no overwriting of existing names).



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/y_support/name_magic.rb', line 131

def name=( name )
  old_

#name_set_hook(&block) ⇒ Object

Registers a hook to execute upon instance naming. Instance’s ‘#name_set_hook` Behaves analogically as namespace’s ‘#name_set_hook`, and is executed right after the namespace’s hook. Expects a block with a single argument, name of the instance. The return value of the block is not used and should be nil. Without a block, this method acts as a getter.



179
180
181
182
# File 'lib/y_support/name_magic.rb', line 179

def name_set_hook &block
  tap { @name_set_hook = block } if block
  @name_set_hook ||= -> name { nil }
end

#namespaceObject

The namespace of the instance’s class.



97
98
99
# File 'lib/y_support/name_magic.rb', line 97

def namespace
  self.class.namespace
end

#to_sObject

Default #to_s method for NameMagic includers, returning the name.



186
187
188
# File 'lib/y_support/name_magic.rb', line 186

def to_s
  name ? name.to_s : super
end