module MetaRuby::Registration

Handling of registration of model hierarchies

It depends on the mixed-in object to provide a supermodel method that returns the model that is parent of self

Attributes

definition_location[RW]

The place where this model got defined in the source code This is an array of Thread::Backtrace::Locations

@return [Array<Thread::Backtrace::Locations>]

Public Class Methods

accessible_by_name?(object) click to toggle source

@return [Boolean] true if the given object can be accessed by resolving its

name as a constant
# File lib/metaruby/registration.rb, line 54
def self.accessible_by_name?(object)
    return false if !object.respond_to?(:name) || !object.name
    begin
        constant("::#{object.name}") == object
    rescue NameError
        false
    end
end
deregister_constant(obj) click to toggle source

Removes the constant that stores the given object in the Ruby constant hierarchy

It assumes that calling name on the object returns the place in the constant hierarchy where it is stored

# File lib/metaruby/registration.rb, line 133
def self.deregister_constant(obj)
    constant("::#{obj.spacename}").send(:remove_const, obj.basename)
end

Public Instance Methods

accessible_by_name?() click to toggle source

@return [Boolean] true if this object can be accessed by resolving its

name as a constant
# File lib/metaruby/registration.rb, line 65
def accessible_by_name?
    Registration.accessible_by_name?(self)
end
clear_model() click to toggle source

Clears this model

It deregisters sef if it is not a {#permanent_model?}, and clears the submodels

Model classes and modules should also clear their respective attributes (if there are any)

# File lib/metaruby/registration.rb, line 109
def clear_model
    if !permanent_model?
        if m = supermodel
            m.deregister_submodels([self])
        end
        clear_registration_as_constant
    end
    clear_submodels
end
clear_registration_as_constant() click to toggle source

Removes any constant this model is registered as

# File lib/metaruby/registration.rb, line 120
def clear_registration_as_constant
    # Deregister non-permanent models that are registered in the
    # constant hierarchy
    if Registration.accessible_by_name?(self)
        Registration.deregister_constant(self)
    end
end
clear_submodels() click to toggle source

Recursively deregisters all non-permanent submodels

# File lib/metaruby/registration.rb, line 138
def clear_submodels
    permanent, non_permanent = each_submodel.partition { |m| m.permanent_model? }
    if !non_permanent.empty?
        deregister_submodels(non_permanent)
    end

    non_permanent.each do |m|
        m.clear_registration_as_constant
    end

    # This contains the permanent submodels
    #
    # We can call #clear_submodels while iterating here as it is a
    # constraint that all models in #submodels are permanent (and
    # will therefore not be removed)
    permanent.each { |m| m.clear_submodels }
    # And this the non-permanent ones
    non_permanent.each { |m| m.clear_submodels }
    true
end
deregister_submodels(set) click to toggle source

@api private

Deregisters a set of submodels on this model and all its supermodels

This is usually not called directly. Use clear_submodels instead

@param [Set] set the set of submodels to remove

# File lib/metaruby/registration.rb, line 167
def deregister_submodels(set)
    has_match = false
    submodels.delete_if do |m|
        begin
            m = m.__getobj__
            if set.include?(m)
                has_match = true
            end
        rescue WeakRef::RefError
            true
        end
    end

    if m = supermodel
        m.deregister_submodels(set)
    end
    has_match
end
each_submodel() { |__getobj__| ... } click to toggle source

Enumerates all models that are submodels of this class

# File lib/metaruby/registration.rb, line 90
def each_submodel
    return enum_for(:each_submodel) if !block_given?
    submodels.delete_if do |obj|
        begin
            yield(obj.__getobj__)
            false
        rescue WeakRef::RefError
            true
        end
    end
end
has_submodel?(model) click to toggle source

Returns whether a model is a submodel of self

# File lib/metaruby/registration.rb, line 30
def has_submodel?(model)
    each_submodel.any? { |m| m == model }
end
permanent_definition_context?() click to toggle source

@return [Boolean] true if the definition context (module, class) in

which self is registered is permanent or not w.r.t. the model
registration functionality of metaruby
# File lib/metaruby/registration.rb, line 37
def permanent_definition_context?
    return false if !name
    definition_context_name = spacename
    if !definition_context_name.empty?
        begin
            enclosing_context = constant("::#{definition_context_name}")
            return !enclosing_context.respond_to?(:permanent_model?) || enclosing_context.permanent_model?
        rescue NameError
            false
        end
    else
        true
    end
end
register_submodel(klass) click to toggle source

Call to register a model that is a submodel of self

# File lib/metaruby/registration.rb, line 70
def register_submodel(klass)
    if klass.singleton_class?
        raise ArgumentError, "cannot register a singleton class"
    end

    if !klass.definition_location
        klass.definition_location = 
            if MetaRuby.keep_definition_location?
                caller_locations
            else Array.new
            end
    end

    submodels << WeakRef.new(klass)
    if m = supermodel
        m.register_submodel(klass)
    end
end