Module: Eco::API::Common::ClassAutoLoader

Includes:
ClassHelpers
Included in:
People::PersonParser, UseCases
Defined in:
lib/eco/api/common/class_auto_loader.rb

Overview

Note:
  • this helpers aim to boost the usage of the ruby language in complex api configurations.

Helpers for dynamic object loading based on class declaration

Instance Method Summary collapse

Methods included from ClassHelpers

#class_resolver, #descendants, #descendants?, #inheritable_attrs, #inheritable_class_vars, #inherited, #instance_variable_name, #new_class, #resolve_class, #to_constant

Instance Method Details

#_autoload_namespace(type, *namespaces) ⇒ Object



38
39
40
# 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) ⇒ Boolean

It loads/creates a new instance of children classes pending to be loaded.

Returns:

  • (Boolean)

    true if there were children loaded, false otherwise.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# 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|
    begin
      @child = klass.new(object)
    rescue TypeError => e
      # Can't create from this class (must be the singleton class)
      # Just ignore
    ensure
      autoloaded_children.push(klass)
    end
  end
  @loading_children = false
  true
end

#autoload_class?(constant) ⇒ Boolean

Returns determines if a given namespace is entitled for autoloading.

Parameters:

  • constant (Class, String)

    a class or namespace we want to check auto-load entitlement thereof.

Returns:

  • (Boolean)

    determines if a given namespace is entitled for autoloading



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 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) ⇒ Object

To restrict which namespaces it is allowed to load from



29
30
31
# File 'lib/eco/api/common/class_auto_loader.rb', line 29

def autoload_namespace(*namespaces)
  _autoload_namespace(:include, *namespaces)
end

#autoload_namespace_ignore(*namespaces) ⇒ Object

To ignore certain namespaces this class should not autoload from



34
35
36
# File 'lib/eco/api/common/class_auto_loader.rb', line 34

def autoload_namespace_ignore(*namespaces)
  _autoload_namespace(:ignore, *namespaces)
end

#autoloaded_childrenObject

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



61
62
63
# File 'lib/eco/api/common/class_auto_loader.rb', line 61

def autoloaded_children
  @auto_loaded_children ||= []
end

#autoloaded_classObject

Resolves the class autoloader_class if it has been defined via autoloads_children_of



17
18
19
20
# 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) ⇒ Object

To which restricted namespaces this class autoloads from



23
24
25
26
# 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) ⇒ Object

To enable the class autoloader, you should use this method



11
12
13
14
# 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) ⇒ Object

Add to known namespaces



103
104
105
# File 'lib/eco/api/common/class_auto_loader.rb', line 103

def known_class!(*classes)
  known_classes.concat(classes)
end

#known_classesObject

Known namespaces serves the purpose to discover recently added namespaces provided that the namespace discovery is optimized



98
99
100
# File 'lib/eco/api/common/class_auto_loader.rb', line 98

def known_classes
  @known_classes ||= []
end

#new_classesObject

List all new namespaces



108
109
110
# File 'lib/eco/api/common/class_auto_loader.rb', line 108

def new_classes
  ObjectSpace.each_object(::Class).to_a - known_classes
end

#unloaded_childrenObject

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



66
67
68
69
70
71
72
73
# 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