Class: Ruber::ComponentManager::PluginSorter
- Defined in:
- lib/ruber/component_manager.rb
Overview
Helper class used to resolve dependencies among plugins. Most likely you don’t need to use it, but simply call Ruber::ComponentManager.sort_plugins
.
Instance Method Summary collapse
-
#initialize(pdfs, ignored = []) ⇒ PluginSorter
constructor
Creates a new
PluginSorter
. -
#sort_plugins ⇒ Object
Sorts the plugins associated with the object, according with their dependencies and returns an array containing the plugin descriptions sorted in dependence order, from the dependence to the dependent.
Constructor Details
#initialize(pdfs, ignored = []) ⇒ PluginSorter
Creates a new PluginSorter
. pdfs is an array of the plugin descriptions to sort. ignored is an array containing dependencies to be ignored(maybe because they’re already loaded). ignored can be either an array of symbols, where each symbol is the name of a feature, or an array of PluginSpecifications.
Note: pdfs should contain dependencies in terms of actual plugins, not of features.
67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/ruber/component_manager.rb', line 67 def initialize pdfs, ignored = [] @pdfs = {} @plugins = {} pdfs.each do |i| @pdfs[i.name] = i @plugins[i.name] = i.deps end @ignored = ignored.map{|i| i.is_a?(OpenStruct) ? i.name : i} @ready = [] @deps = {} end |
Instance Method Details
#sort_plugins ⇒ Object
Sorts the plugins associated with the object, according with their dependencies and returns an array containing the plugin descriptions sorted in dependence order, from the dependence to the dependent.
If some of the plugins have dependency which doesn’t correspond neither to another plugin nor to one of the plugins to ignore, Ruber::ComponentManager::UnresolvedDep
will be raised.
If there’s a circular dependency among the plugins, Ruber::ComponentManager::CircularDep
will be raised.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/ruber/component_manager.rb', line 91 def sort_plugins @plugins.each_value do |v| v.reject!{|d| @ignored.include? d} end unknown = find_unknown_deps raise ComponentManager::UnresolvedDep.new unknown unless unknown.empty? circular = @plugins.keys.inject([]){ |res, plug| res + find_dep( plug ) } raise ComponentManager::CircularDep.new(circular.uniq) unless circular.empty? deps = @deps.reject{|k, v| v.nil? } res = [] old_size = deps.size until deps.empty? ready = deps.select{|k, v| v.empty?}.map{|i| i[0]}.sort_by{|i| i.to_s} res += ready ready.each do |i| deps.each{|d| d[1].delete i} deps.delete i end raise "Circular deps (this shouldn't happen)" unless old_size > deps.size old_size = deps.size end res.map{|i| @pdfs[i]} end |