Erik Hollensbe wrote:
> Matthew Moss wrote:
>> What I would like is a script that works like `which` but for Ruby
>> modules. Examples:
> 
> Here's my solution:
> 
> [68] erikh@islay ~% ruby quiz.rb date
> /usr/lib/ruby/1.8/date.rb
> [69] erikh@islay ~% ruby quiz.rb date digest/sha1
> /usr/lib/ruby/1.8/date.rb
> /usr/lib/ruby/1.8/x86_64-linux/digest/sha1.so
> [70] erikh@islay ~% irb -r quiz.rb
> irb(main):001:0> require 'digest/sha1'
> /usr/lib/ruby/1.8/x86_64-linux/digest/sha1.so
> => true
> irb(main):002:0> require 'date'
> /usr/lib/ruby/1.8/date.rb
> /usr/lib/ruby/1.8/rational.rb
> /usr/lib/ruby/1.8/date/format.rb
> /usr/lib/ruby/1.8/rational.rb
> => true


Here's the code:

#!/usr/bin/env ruby

module Kernel
    def require_which(filespec)
        $:.each do |path|
            spec_parts = filespec.split(/\//)

            files = Dir[File.join(path, *spec_parts) + ".*"]
            unless files.empty?
                return files
            end
        end

        [ ]
    end
end

if __FILE__ == $0
    ARGV.each do |arg|
        require_which(arg).each { |f| puts f }
    end
else
    module Kernel
        @@old_require = Kernel.method(:require)
        def require(*args)
            require_which(args[0]).each { |f| puts f }
            @@old_require.call(*args)
        end
    end
end

Benefits:

1) Should properly work on windows (or anything with a weird pathspec) 
in any situation
2) catches .so/.bundle/.whatever
3) terminates early to avoid catching things that could be loaded if the 
load path were different, but aren't actually (which is actually against 
how 'which' generally works, but meh)

Drawbacks:
Suffers from the same require-itis mentioned earlier: change def require 
to:

def require(*args)
  res = @@old_require.call(*args)
  if res
    require_which(args[0]).each { |f| puts f }
  end
  return res
end

Which should solve that problem.
-- 
Posted via http://www.ruby-forum.com/.