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
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
@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
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
@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
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
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
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
@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
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
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
@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
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