module Loader module AutoLoad module Support class << self def pwd if !!ENV['BUNDLE_GEMFILE'] ENV['BUNDLE_GEMFILE'].split(File::Separator)[0..-2].join(File::Separator) else Dir.pwd end end def try_load_by(caller_class,name) levels = generate_levels(caller_class, name) ['lib',nil].each do |folder| levels.map{|str| File.join(*[pwd,folder,"#{underscore(str)}.rb"].compact) }.sort{|a,b| b.length <=> a.length }.each do |path| return if File.exist?(path) && require(path) end end end def generate_levels(klass, name) levels = klass.to_s.split('::').reduce([]) { |m, c| m << [(last_obj = m.last), c].compact.join('::');m }.map { |str| [str, name].join('::') } levels.unshift(name.to_s) return levels end def try_fetch_constant(caller_class, name) levels = Support.generate_levels(caller_class, name).map { |str| Regexp.escape(str) } ObjectSpace.each_object(Module) { |obj| if !!(obj.to_s =~ /^(#{levels.join('|')})$/) return obj end };nil end # Based on ActiveSupport, removed inflections. # https://github.com/rails/rails/blob/v4.1.0.rc1/activesupport/lib/active_support/inflector/methods.rb def underscore(camel_cased_word) word = camel_cased_word.to_s.gsub('::', '/') word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2') word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') word.tr!("-", "_") word.downcase! word end end end def const_missing(name) Support.try_load_by(self,name) constant = Support.try_fetch_constant(self, name) if constant return constant else super end end end def self.autoload ::Module.__send__(:prepend,Loader::AutoLoad) end end