Class: Toys::ModuleLookup

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

Constructor Details

#initializeModuleLookup

Create an empty ModuleLookup



77
78
79
# File 'lib/toys/module_lookup.rb', line 77

def initialize
  @paths = []
end

Class Method Details

.path_to_module(path) ⇒ Module

Given a require path, return the module expected to be defined.

Parameters:

  • path (String)

    File path, delimited by forward slash

Returns:

  • (Module)

    The module loaded from that path



63
64
65
66
67
68
69
70
71
# File 'lib/toys/module_lookup.rb', line 63

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.

Parameters:

  • str (String, Symbol)

    String to convert.

Returns:

  • (Symbol)

    Converted name



52
53
54
55
# File 'lib/toys/module_lookup.rb', line 52

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.

Parameters:

  • str (String, Symbol)

    String to convert.

Returns:

  • (String)

    Converted string



39
40
41
42
43
# File 'lib/toys/module_lookup.rb', line 39

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.

Parameters:

  • path_base (String)

    The base require path

  • module_base (Module)

    The base module, or nil (the default) to infer a default from the path base.

  • high_priority (Boolean)

    If true, add to the head of the lookup path, otherwise add to the end.

Returns:

  • (self)


91
92
93
94
95
96
97
98
99
# File 'lib/toys/module_lookup.rb', line 91

def add_path(path_base, module_base: nil, high_priority: false)
  module_base ||= ModuleLookup.path_to_module(path_base)
  if high_priority
    @paths.unshift([path_base, module_base])
  else
    @paths << [path_base, module_base]
  end
  self
end

#lookup(name) ⇒ Module

Obtain a named module. Returns nil if the name is not present.

Parameters:

  • name (String, Symbol)

    The name of the module to return.

Returns:

  • (Module)

    The specified module



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/toys/module_lookup.rb', line 107

def lookup(name)
  @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
  nil
end