Module: NameMagic

Defined in:
lib/y_support/name_magic.rb

Overview

This mixin imitates Ruby constant magic and automates the named argument :name (alias :ɴ). One thus can write:

class Someclass; include NameMagic end SomeName = SomeClass.new

and the resulting object will know its #name:

SomeName.name = "SomeName"

This is done by searching the whole Ruby namespace for constants, to which the object might have been assigned. The search is performed by the method #const_magic defined by this mixin. Once the object is found to be assigned to a constant, and named accordingly, its subsequent assignments to other constants have no additional effect.

Alternative way to create a named object is by specifying :name (alias :ɴ) named argument:

SomeClass.new a, b, ..., name: "SomeName", aa: v1, bb: v2 ...

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(ɱ) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/y_support/name_magic.rb', line 36

def self.included ɱ
  case ɱ
  when Class then # we will decorate its #new method
    class << ɱ
      alias :original_method_new :new # Make space to decorate #new
    end
    # Attach the decorators etc.
    ɱ.extend ::NameMagic::ClassMethods
    ɱ.extend ::NameMagic::NamespaceMethods
    # Attach namespace methods also to the namespace, if given.
    begin
      if ɱ.namespace == ɱ then
        ɱ.define_singleton_method :namespace do ɱ end
      else
        ɱ.namespace.extend ::NameMagic::NamespaceMethods
      end
    rescue NoMethodError
    end
  else # it is a Module; we'll infect it with our #included method
    ɱ_included, this_included = ɱ.method( :included ), method( :included )
    ɱ.define_singleton_method :included do |ç|
      this_included.( ç )
      ɱ_included.( ç )
    end
  end
end

Instance Method Details

#nameObject Also known as: ɴ

Retrieves an instance name (demodulized).



65
66
67
68
69
70
71
72
# File 'lib/y_support/name_magic.rb', line 65

def name
  self.class.const_magic
  ɴ = self.class.__instances__[ self ]
  if ɴ then
    name_get_closure = self.class.instance_variable_get :@name_get_closure
    name_get_closure ? name_get_closure.( ɴ ) : ɴ
  else nil end
end

#name!(ɴ) ⇒ Object

Names an instance, aggresively (overwrites existing names).



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/y_support/name_magic.rb', line 105

def name!( ɴ )
  puts "NameMagic: Rudely naming with argument #{ɴ}." if DEBUG
  old_ɴ = self.class.__instances__[ self ] # get instance's old name, if any
  # honor the hook
  name_set_closure = self.class.instance_variable_get :@name_set_closure
  ɴ = name_set_closure.( ɴ, self, old_ɴ ) if name_set_closure
  ɴ = self.class.send( :validate_capitalization, ɴ ).to_sym
  puts "NameMagic: Name adjusted to #{ɴ}." if DEBUG
  return false if old_ɴ == ɴ # already named as required; nothing to do
  # otherwise, rudely remove the collider, if any
  pair = self.class.__instances__.rassoc( ɴ )
  self.class.__forget__( pair[0] ) if pair
  # and add self to the namespace instead
  self.class.namespace.const_set ɴ, self # write a constant
  self.class.__instances__[ self ] = ɴ   # write to __instances__
  self.class.__forget__ old_ɴ            # forget the old name of self
  return true
end

#name=(ɴ) ⇒ Object

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

Raises:

  • (NameError)


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/y_support/name_magic.rb', line 84

def name=( ɴ )
  puts "NameMagic: Naming with argument #{ɴ}." if DEBUG
  # get previous name of this instance, if any
  old_ɴ = self.class.__instances__[ self ]
  # honor the hook
  name_set_closure = self.class.instance_variable_get :@name_set_closure
  ɴ = name_set_closure.call( ɴ, self, old_ɴ ) if name_set_closure
  ɴ = self.class.send( :validate_capitalization, ɴ ).to_sym
  puts "NameMagic: Name adjusted to #{ɴ}." if DEBUG
  return if old_ɴ == ɴ # already named as required; nothing to do
  # otherwise, be cautious about name collision
  raise NameError, "Name '#{ɴ}' already exists in " +
    "#{self.class} namespace!" if self.class.__instances__.rassoc( ɴ )
  # since everything's ok...
  self.class.namespace.const_set ɴ, self # write a constant
  self.class.__instances__[ self ] = ɴ   # write __instances__
  self.class.__forget__ old_ɴ            # forget the old name of self
end

#name_or_object_idObject Also known as: ɴ_

Retrieves either an instance name (if present), or an object id.



77
78
79
# File 'lib/y_support/name_magic.rb', line 77

def name_or_object_id
  name || object_id
end