Module: MetaRuby::Registration

Included in:
ModelAsClass, ModelAsModule
Defined in:
lib/metaruby/registration.rb

Overview

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#definition_locationArray<(String,Integer,Symbol)>

The place where this model got defined in the source code The tuple is (file,lineno,method), and can be obtained with facet’s #call_stack

Returns:

  • (Array<(String,Integer,Symbol)>)


17
18
19
# File 'lib/metaruby/registration.rb', line 17

def definition_location
  @definition_location
end

Class Method Details

.accessible_by_name?(object) ⇒ Boolean

Returns true if the given object can be accessed by resolving its name as a constant.

Returns:

  • (Boolean)

    true if the given object can be accessed by resolving its name as a constant



55
56
57
58
59
60
61
62
# File 'lib/metaruby/registration.rb', line 55

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

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



123
124
125
# File 'lib/metaruby/registration.rb', line 123

def self.deregister_constant(obj)
    constant("::#{obj.spacename}").send(:remove_const, obj.basename)
end

Instance Method Details

#accessible_by_name?Boolean

Returns true if this object can be accessed by resolving its name as a constant.

Returns:

  • (Boolean)

    true if this object can be accessed by resolving its name as a constant



66
67
68
# File 'lib/metaruby/registration.rb', line 66

def accessible_by_name?
    Registration.accessible_by_name?(self)
end

#clear_modelObject

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)



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/metaruby/registration.rb', line 106

def clear_model
    if !permanent_model?
        if m = supermodel
            m.deregister_submodels([self])
        end
        if Registration.accessible_by_name?(self)
            Registration.deregister_constant(self)
        end
    end
    clear_submodels
end

#clear_submodelsObject

Recursively deregisters all non-permanent submodels



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/metaruby/registration.rb', line 128

def clear_submodels
    children = each_submodel.find_all { |m| !m.permanent_model? }
    if !children.empty?
        deregister_submodels(children)
    end

    children.each do |m|
        # Deregister non-permanent models that are registered in the
        # constant hierarchy
        if Registration.accessible_by_name?(m)
            Registration.deregister_constant(m)
        end
    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)
    each_submodel { |m| m.clear_submodels }
    # And this the non-permanent ones
    children.each { |m| m.clear_submodels }
    true
end

#deregister_submodels(set) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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

This is usually not called directly. Use #clear_submodels instead

Parameters:

  • set (Set)

    the set of submodels to remove



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/metaruby/registration.rb', line 161

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_submodelObject

Enumerates all models that are submodels of this class



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/metaruby/registration.rb', line 87

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) ⇒ Boolean

Returns whether a model is a submodel of self

Returns:

  • (Boolean)


31
32
33
# File 'lib/metaruby/registration.rb', line 31

def has_submodel?(model)
    each_submodel.any? { |m| m == model }
end

#permanent_definition_context?Boolean

Returns 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.

Returns:

  • (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



38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/metaruby/registration.rb', line 38

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

#permanent_model?Boolean

Tells #clear_submodels whether this model should be removed from the model set or not. The default is false (it should be removed)

Returns:

  • (Boolean)


23
# File 'lib/metaruby/registration.rb', line 23

attr_predicate :permanent_model?, true

#register_submodel(klass) ⇒ Object

Call to register a model that is a submodel of self



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/metaruby/registration.rb', line 71

def register_submodel(klass)
    if !klass.definition_location
        klass.definition_location = 
            if MetaRuby.keep_definition_location?
                call_stack
            else Array.new
            end
    end

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

#submodelsArray<WeakRef>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the set of models that are children of this one.

Returns:

  • (Array<WeakRef>)

    the set of models that are children of this one



28
# File 'lib/metaruby/registration.rb', line 28

attribute(:submodels) { Array.new }