Module: ModuleExtensions::Hierarchy

Included in:
Module
Defined in:
lib/module_extensions/hierarchy.rb,
lib/module_extensions/hierarchy.rb

Overview

Extend the Module class with methods to manipulate inheritance relation between constants of a module.

Instance Method Summary collapse

Instance Method Details

#remove_class(base_class, recursive = false) ⇒ Object

Remove a class from the hierarchy using remove_const. Sub classes of this class are also removed. It returns an array of the removed class name. See sub_classes for a description of the recursive argument.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/module_extensions/hierarchy.rb', line 36

def remove_class(base_class, recursive=false)
  subs = sub_classes(base_class, true, recursive)
  re = /^#{name}::/
  result = []
  subs.each do |sub|
    sub_name = sub.to_s.sub!(re, '')
    if sub_name =~ /^(.+)::(.+)$/
      const_get($1).module_eval { remove_const($2.to_sym) }
    else
      remove_const(sub_name.to_sym)
    end
    result << sub_name
  end
  result
end

#sub_classes(base_class, force_autoload = false, recursive = false) ⇒ Object

Return the list of all sub classes of base_class (including itself). If force_autoload is false, not yet loaded constants will be ignored. If recursive is true sub modules will also be traversed.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/module_extensions/hierarchy.rb', line 15

def sub_classes(base_class, force_autoload=false, recursive=false)
  check_const_is_class?(base_class)
  result = []
  constants.each do |const_name|
    if autoload?(const_name).nil? or force_autoload
      const = const_get(const_name)
      if const.is_a?(Module)
        if const.is_a?(Class)
          result << const if const.ancestors.include?(base_class)
        elsif recursive
          result += const.sub_classes(base_class, force_autoload, recursive)
        end
      end
    end
  end
  result
end

#sub_classes_tree(base_class, force_autoload = false, recursive = false) ⇒ Object

Return the inheritance tree of the base_class. Example:

module M

class A; end
class B < A; end
class C < B; end
class D < B; end
class E < A; end
module N
  class F < A; end
  class G < F; end
  class H < D; end
  class I < H; end
  class J < E; end
  class Y; end
end
class Z; end
FOO = 42

end

M.sub_classes_tree(M::A)

produces:

M::A => {
  M::B => {
    M::D => {,
    M::C => {}
  },
  M::E => {}
}

}

and

M.sub_classes_tree(M::A, false, true)

produces:

{

M::A => {
  M::N::F => {
    M::N::G => {}
  },
  M::B => {
    M::C => {},
    M::D => {
      M::N::H => {
        M::N::I => {}
      }
    }
  },
  M::E => {
    M::N::J => {}
  }
}

}



111
112
113
114
# File 'lib/module_extensions/hierarchy.rb', line 111

def sub_classes_tree(base_class, force_autoload=false, recursive=false)
  subs = sub_classes(base_class, force_autoload, recursive)
  sub_classes_tree_rec([base_class], subs)
end