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

[View source]

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.

[View source]

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

[View source]

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

[View source]

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

[View source]

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.

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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.

[View source]

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