Module: RakeCommander::Base::ClassAutoLoader

Includes:
ClassHelpers
Defined in:
lib/rake-commander/base/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

Constant Summary

Constants included from ClassHelpers

RakeCommander::Base::ClassHelpers::NOT_USED

Instance Method Summary collapse

Methods included from ClassHelpers

#class_resolver, #descendants, #descendants?, #new_class, #redef_without_warning, #resolve_class, #sort_classes, #to_constant, #used_param?

Instance Method Details

#_autoload_namespace(type, *namespaces) ⇒ Object

Applies a change to the autoloaded_namespaces



40
41
42
43
44
45
46
47
# File 'lib/rake-commander/base/class_auto_loader.rb', line 40

def _autoload_namespace(type, *namespaces)
  autoloaded_namespaces(type).tap do |target|
    next if namespaces.empty?
    other_type = type == :include ? :ignore : :include
    namespaces.each {|nm_sp| autoloaded_namespaces(other_type).delete(nm_sp)}
    target.concat(namespaces)
  end
end

#autoload_children(object = nil) ⇒ Boolean

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

Returns:

  • (Boolean)

    true if there were children loaded, false otherwise.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/rake-commander/base/class_auto_loader.rb', line 106

def autoload_children(object = nil)
  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|
    exclude = false
    child   = object ? klass.new(object) : klass.new
    yield(child) if block_given?
  rescue TypeError
    # Can't create from this class (must be the singleton class)
    exclude = true
    excluded_children.push(klass)
  ensure
    autoloaded_children.push(klass) unless exclude
  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



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rake-commander/base/class_auto_loader.rb', line 51

def autoload_class?(constant)
  constants = constant.to_s.split("::").compact
  autoload = true
  unless autoloaded_namespaces(:include).empty?
    autoload = autoloaded_namespaces(:include).any? do |ns|
      ns.to_s.split("::").compact.zip(constants).all? {|(r, c)| r == c}
    end
  end
  unless autoloaded_namespaces(:ignore).empty?
    autoload &&= autoloaded_namespaces(:ignore).none? do |ns|
      ns.to_s.split("::").compact.zip(constants).all? {|(r, c)| r == c}
    end
  end
  autoload
end

#autoload_namespace(*namespaces) ⇒ Object

Note:

this deletes from the :ignore namespaces

To restrict which namespaces it is allowed to load from



29
30
31
# File 'lib/rake-commander/base/class_auto_loader.rb', line 29

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

#autoload_namespace_ignore(*namespaces) ⇒ Object

Note:

this deletes from the :include namespaces

To ignore certain namespaces this class should not autoload from



35
36
37
# File 'lib/rake-commander/base/class_auto_loader.rb', line 35

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.



68
69
70
# File 'lib/rake-commander/base/class_auto_loader.rb', line 68

def autoloaded_children
  @autoloaded_children ||= []
end

#autoloaded_classObject

Resolves the class autoloader_class if it has been defined via autoloads_children_of



16
17
18
19
# File 'lib/rake-commander/base/class_auto_loader.rb', line 16

def autoloaded_class
  return nil unless @autoloaded_class
  autoloader_class
end

#autoloaded_namespaces(type = :include) ⇒ Object

To which restricted namespaces this class autoloads from



22
23
24
25
# File 'lib/rake-commander/base/class_auto_loader.rb', line 22

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



10
11
12
13
# File 'lib/rake-commander/base/class_auto_loader.rb', line 10

def autoloads_children_of(klass)
  class_resolver :autoloader_class, klass
  @autoloaded_class = klass
end

#clear_autoloaded_childrenObject

Note:

it may be handy some times.

Allows to reload



79
80
81
82
83
# File 'lib/rake-commander/base/class_auto_loader.rb', line 79

def clear_autoloaded_children
  forget_class!(*autoloaded_children, *ignored_children)
  @ignored_children    = []
  @autoloaded_children = []
end

#excluded_childrenObject

Prevents already excluded children to enter into the loop again.



86
87
88
# File 'lib/rake-commander/base/class_auto_loader.rb', line 86

def excluded_children
  @excluded_children ||= []
end

#forget_class!(*classes) ⇒ Object

Forget namespaces



139
140
141
142
# File 'lib/rake-commander/base/class_auto_loader.rb', line 139

def forget_class!(*classes)
  @known_classes = known_classes - classes
  self
end

#ignored_childrenObject

Keep track on actual children that have been ignored by autoload_namespace_ignore.



73
74
75
# File 'lib/rake-commander/base/class_auto_loader.rb', line 73

def ignored_children
  @ignored_children ||= []
end

#known_class!(*classes) ⇒ Object

Add to known namespaces



133
134
135
136
# File 'lib/rake-commander/base/class_auto_loader.rb', line 133

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

#known_classesObject

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



128
129
130
# File 'lib/rake-commander/base/class_auto_loader.rb', line 128

def known_classes
  @known_classes ||= []
end

#new_classesObject

List all new namespaces



145
146
147
# File 'lib/rake-commander/base/class_auto_loader.rb', line 145

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.



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rake-commander/base/class_auto_loader.rb', line 91

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) && \
      !excluded_children.include?(child_class) && \
      autoload_class?(child_class).tap do |ignored|
        ignored_children.push(child_class) if ignored
      end
  end
end