Module::Require

Rubygemsのライブラリのソースを眺めていると、

  $:.unshift(File.dirname(__FILE__))
  require "hoge"

とか

  require File.dirname(__FILE__) + "hoge"

とか書かれてたりするけど、見た目がなぁ…ということで、こんなの書いてみた。

walf443@colinux:module_require% head -n 10000 lib/module_require.rb
class Module                    
  #                             
  # Module::Require             
  #                             
  # you can write simply to load the same project files.
  #                             
  # ==SYNOPSYS==                
  #                             
  # # path/to/some_module.rb    
  # require 'rubygems'          
  # require 'module_require'    
  #                             
  # module SomeModule           
  #   module_require "some_module/hoge" # load path/to/some_module/hoge.rb
  #   
  #   def hoge
  #     ...
  #   end
  #   
  #   ...
  # end
  # 
  #
  # # path/to/some/that.rb
  # class Some
  #   class That
  #     class_require "some" # you can also use "class_require" to load path/to/some.rb
  #     class_require "open-uri" # if not exist path/to/open-uri, require "open-uri"
  #   end
  # end
  #
  private

  def module_require(str)
    unless @top_level_namespace_dir
      module_filename = File.expand_path(caller.first.sub(/:.*/, ''))
      @top_level_namespace_dir = module_filename.sub(/#{Module::Require.underscore(self)}.*/, '')
    end
    
    require @top_level_namespace_dir + str.to_s
  rescue LoadError
    require str.to_s
  end

  alias class_require module_require  # alias mod_require   module_require # do you need this?
  
  module Require
    def underscore(const)
      const.to_s.
        gsub(/::/, "/").
        gsub(/([A-Z]+$)/, '_\1').
        gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
        gsub(/([a-z\d])([A-Z])/, '\1_\2').
        sub(/^_/, '').
        downcase
    end
    
    module_function :underscore
  end
end

需要がありそうならRubygemsに上げるかも。まぁ一行書くか、こんなのダウンロードしてrequireするかだったら一行書いて済ませてしまうような気もする…。