class Metasploit::Concern::Loader
Loads ActiveSupport::Concerns (or anything that can be passed to ‘include` really) under {#root}
Attributes
@!attribute [rw] root
Pathname under which to find concerns. @return [Pathname]
Public Class Methods
Source
# File lib/metasploit/concern/loader.rb, line 55 def initialize(attributes={}) attributes.each do |attribute, value| public_send("#{attribute}=", value) end end
@param attributes [Hash{Symbol => String,nil}]
Public Instance Methods
Source
# File lib/metasploit/concern/loader.rb, line 35 def each_pathname_constant(parent_pathname:) parent_pathname.each_child do |child_pathname| constant = constantize_pathname( pathname: child_pathname ) if constant yield constant end end end
Yields each constant under ‘parent_pathname`.
@param mechanism [:constantize, :require] ‘:require` if child pathname should be required so that the constant
cannot be unloaded by `ActiveSupport::Dependencies.clear`.
@param parent_pathname [Pathname] @yield [constant] @yieldparam constant [Module] constant declared under ‘parent_pathname`. @yieldreturn [void] @return [void]
Source
# File lib/metasploit/concern/loader.rb, line 50 def glob root.join('**', '*.rb') end
Glob pattern for concerns.
@return [Pathname]
Source
# File lib/metasploit/concern/loader.rb, line 64 def module_pathname_set concern_paths = Dir.glob(glob) concern_paths.each_with_object(Set.new) { |concern_path, module_pathname_set| concern_pathname = Pathname.new(concern_path) module_pathname = concern_pathname.parent module_pathname_set.add module_pathname } end
Set of Pathnames for ‘Module`s that will have concerns included.
@return [Set<Pathname>]
Source
# File lib/metasploit/concern/loader.rb, line 78 def register module_pathname_set.each do |module_pathname| relative_module_pathname = module_pathname.relative_path_from(root) relative_module_path = relative_module_pathname.to_path underscored_module_name = relative_module_path.gsub(File::SEPARATOR, '_') on_load_name = underscored_module_name.to_sym # on_load block is instance_evaled, so need to capture self loader = self ActiveSupport.on_load(on_load_name) do loader.each_pathname_constant(parent_pathname: module_pathname) do |concern| include concern unless self.ancestors.map(&:name).include?(concern.to_s) end end end end
Registers load hooks with ‘ActiveSupport.on_load`.
@return [void]
Private Instance Methods
Source
# File lib/metasploit/concern/loader.rb, line 105 def constantize_pathname(pathname:) constant_name = pathname_to_constant_name(pathname) constant = nil if constant_name begin # constantize either way as the the constant_name still needs to be converted to Module constant = constant_name.constantize rescue => e # rescue any here should probably be more specific if e.kind_of?(NameError) begin require pathname constant = constant_name.constantize rescue NameError => _e _e # left for debugging breakpoint end end end end constant end
Converts ‘descendant_pathname`, which should be under {#root}, into a constant.
@param mechanism [:constantize, :require] ‘:require` if pathname should be required so that the constant cannot be
unloaded by `ActiveSupport::Dependencies.clear`.
@param pathname [Pathname] a Pathname under {#root}. @return [Object] if {#pathname_to_constant_name} returns a constant name @return [nil] otherwise
Source
# File lib/metasploit/concern/loader.rb, line 132 def pathname_to_constant_name(descendant_pathname) extension_name = descendant_pathname.extname constant_name = nil if extension_name == '.rb' constant_pathname = descendant_pathname.relative_path_from(root) constant_name = constant_pathname.to_s.gsub(/.rb$/, '').camelize end constant_name end
Converts ‘descendant_pathname`, which should be under {#root}, into a constant name.
@param descendant_pathname [Pathname] a Pathname under {#root}.