module Eco::API::Common::ClassAutoLoader

Helpers for dynamic object loading based on class declaration @note

- this helpers aim to boost the usage of the ruby language in complex api configurations.

Public Instance Methods

_autoload_namespace(type, *namespaces) click to toggle source
# File lib/eco/api/common/class_auto_loader.rb, line 38
def _autoload_namespace(type, *namespaces)
  autoloaded_namespaces(type).concat(namespaces) unless namespaces.empty?
end
autoload_children(object) click to toggle source

It loads/creates a new instance of children classes pending to be loaded. @return [Boolean] `true` if there were children loaded, `false` otherwise.

# File lib/eco/api/common/class_auto_loader.rb, line 77
def autoload_children(object)
  return false if !autoloaded_class || @loading_children
  pending_children = unloaded_children
  return false if pending_children.empty?
  @loading_children = true
  pending_children.each do |klass|
    @child = klass.new(object)
    autoloaded_children.push(klass)
  end
  @loading_children = false
  true
end
autoload_class?(constant) click to toggle source

@param constant [Class, String] a class or namespace we want to check auto-load entitlement thereof. @return [Boolean] determines if a given namespace is entitled for autoloading

# File lib/eco/api/common/class_auto_loader.rb, line 44
def autoload_class?(constant)
  constants = "#{constant}".split("::").compact
  autoload = true
  unless autoloaded_namespaces(:include).empty?
    autoload = autoloaded_namespaces(:include).any? do |ns|
      "#{ns}".split("::").compact.zip(constants).all? {|(r, c)| r == c}
    end
  end
  unless autoloaded_namespaces(:ignore).empty?
    autoload &&= autoloaded_namespaces(:ignore).none? do |ns|
      "#{ns}".split("::").compact.zip(constants).all? {|(r, c)| r == c}
    end
  end
  autoload
end
autoload_namespace(*namespaces) click to toggle source

To restrict which namespaces it is allowed to load from

# File lib/eco/api/common/class_auto_loader.rb, line 29
def autoload_namespace(*namespaces)
  _autoload_namespace(:include, *namespaces)
end
autoload_namespace_ignore(*namespaces) click to toggle source

To ignore certain namespaces this class should not autoload from

# File lib/eco/api/common/class_auto_loader.rb, line 34
def autoload_namespace_ignore(*namespaces)
  _autoload_namespace(:ignore, *namespaces)
end
autoloaded_children() click to toggle source

As children are loaded as they are declared, we should not load twice same children.

# File lib/eco/api/common/class_auto_loader.rb, line 61
def autoloaded_children
  @auto_loaded_children ||= []
end
autoloaded_class() click to toggle source

Resolves the class `autoloader_class` if it has been defined via `autoloads_children_of`

# File lib/eco/api/common/class_auto_loader.rb, line 17
def autoloaded_class
  return nil unless @autoloaded_class
  autoloader_class
end
autoloaded_namespaces(type = :include) click to toggle source

To which restricted namespaces this class autoloads from

# File lib/eco/api/common/class_auto_loader.rb, line 23
def autoloaded_namespaces(type = :include)
  @autoloaded_namespaces       ||= {}
  @autoloaded_namespaces[type] ||= []
end
autoloads_children_of(klass) click to toggle source

To enable the class autoloader, you should use this method

# File lib/eco/api/common/class_auto_loader.rb, line 11
def autoloads_children_of(klass)
  class_resolver :autoloader_class, klass
  @autoloaded_class = klass
end
known_class!(*classes) click to toggle source

Add to known namespaces

# File lib/eco/api/common/class_auto_loader.rb, line 97
def known_class!(*classes)
  known_classes.concat(classes)
end
known_classes() click to toggle source

Known namespaces serves the purpose to discover recently added namespaces

provided that the namespace discovery is optimized
# File lib/eco/api/common/class_auto_loader.rb, line 92
def known_classes
  @known_classes ||= []
end
new_classes() click to toggle source

List all new namespaces

# File lib/eco/api/common/class_auto_loader.rb, line 102
def new_classes
  ObjectSpace.each_object(::Class).to_a - known_classes
end
unloaded_children() click to toggle source

Children classes of `autoloader_class` that have not been created an instance of.

# File lib/eco/api/common/class_auto_loader.rb, line 66
def unloaded_children
  return [] unless autoloaded_class
  new_detected = new_classes
  known_class!(*new_detected)
  descendants(parent_class: autoloaded_class, scope: new_detected).select do |child_class|
    !autoloaded_children.include?(child_class) && autoload_class?(child_class)
  end.sort
end