Class: Toys::ModuleLookup
- Inherits:
-
Object
- Object
- Toys::ModuleLookup
- Defined in:
- lib/toys/module_lookup.rb
Overview
A helper module that provides methods to do module lookups. This is used to obtain named helpers, middleware, and templates from the respective modules.
Class Method Summary collapse
-
.path_to_module(path) ⇒ Module
Given a require path, return the module expected to be defined.
-
.to_module_name(str) ⇒ Symbol
Convert the given string to a module name.
-
.to_path_name(str) ⇒ String
Convert the given string to a path element.
Instance Method Summary collapse
-
#add_path(path_base, module_base: nil, high_priority: false) ⇒ self
Add a lookup path for modules.
-
#initialize ⇒ ModuleLookup
constructor
Create an empty ModuleLookup.
-
#lookup(name) ⇒ Module
Obtain a named module.
Constructor Details
#initialize ⇒ ModuleLookup
Create an empty ModuleLookup
58 59 60 61 62 |
# File 'lib/toys/module_lookup.rb', line 58 def initialize @mutex = ::Monitor.new @paths = [] @paths_locked = false end |
Class Method Details
.path_to_module(path) ⇒ Module
Given a require path, return the module expected to be defined.
44 45 46 47 48 49 50 51 52 |
# File 'lib/toys/module_lookup.rb', line 44 def path_to_module(path) path.split("/").reduce(::Object) do |running_mod, seg| mod_name = to_module_name(seg) unless running_mod.constants.include?(mod_name) raise ::NameError, "Module #{running_mod.name}::#{mod_name} not found" end running_mod.const_get(mod_name) end end |
.to_module_name(str) ⇒ Symbol
Convert the given string to a module name. Specifically, converts
to UpperCamelCase
, and then to a symbol.
33 34 35 36 |
# File 'lib/toys/module_lookup.rb', line 33 def to_module_name(str) str = str.to_s.sub(/^_/, "").sub(/_$/, "").gsub(/_+/, "_") str.to_s.gsub(/(?:^|_)([a-zA-Z])/) { ::Regexp.last_match(1).upcase }.to_sym end |
.to_path_name(str) ⇒ String
Convert the given string to a path element. Specifically, converts
to lower_snake_case
.
20 21 22 23 24 |
# File 'lib/toys/module_lookup.rb', line 20 def to_path_name(str) str = str.to_s.sub(/^_/, "").sub(/_$/, "").gsub(/_+/, "_") while str.sub!(/([^_])([A-Z])/, "\\1_\\2") do end str.downcase end |
Instance Method Details
#add_path(path_base, module_base: nil, high_priority: false) ⇒ self
Add a lookup path for modules.
74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/toys/module_lookup.rb', line 74 def add_path(path_base, module_base: nil, high_priority: false) module_base ||= ModuleLookup.path_to_module(path_base) @mutex.synchronize do raise "You cannot add a path after a lookup has already occurred." if @paths_locked if high_priority @paths.unshift([path_base, module_base]) else @paths << [path_base, module_base] end end self end |
#lookup(name) ⇒ Module
Obtain a named module. Returns nil
if the name is not present.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/toys/module_lookup.rb', line 93 def lookup(name) @mutex.synchronize do @paths_locked = true @paths.each do |path_base, module_base| path = "#{path_base}/#{ModuleLookup.to_path_name(name)}" begin require path rescue ::LoadError next end mod_name = ModuleLookup.to_module_name(name) unless module_base.constants.include?(mod_name) raise ::NameError, "File #{path.inspect} did not define #{module_base.name}::#{mod_name}" end return module_base.const_get(mod_name) end end nil end |