Whether a simpler solution exists depends on what your motivation is.
Let's look inside the implementation of Gem::Commands::WhichCommand#find_paths
.
def find_paths(package_name, dirs)
result = []
dirs.each do |dir|
Gem.suffixes.each do |ext|
full_path = File.join dir, "#{package_name}#{ext}"
if File.exist? full_path and not File.directory? full_path then
result << full_path
return result unless options[:show_all]
end
end
end
result
end
That's the code you need. If there were a simpler way, find_paths
would have used it.
However, there is a way to cheat: Kernel#require
needs to do a very similar thing when it actually tries to load a module:
require(name) → true or false
Loads the given name
, returning true
if successful and false
if
the feature is already loaded.
If the filename does not resolve to an absolute path, it will be
searched for in the directories listed in $LOAD_PATH
($:
).
If the filename has the extension “.rb”, it is loaded as a source
file; if the extension is “.so”, “.o”, or “.dll”, or the default
shared library extension on the current platform, Ruby loads the
shared library as a Ruby extension. Otherwise, Ruby tries adding
“.rb”, “.so”, and so on to the name until found. If the file named
cannot be found, a LoadError
will be raised.
For Ruby extensions the filename given may use any shared library
extension. For example, on Linux the socket extension is “socket.so”
and require 'socket.dll'
will load the socket extension.
The absolute path of the loaded file is added to $LOADED_FEATURES
($"
). A file will not be loaded again if its path already appears in
$"
. For example, require 'a'; require './a'
will not load a.rb
again.
Or, it might be more accurate to say that find_paths
simulates what require
would do.
Therefore, if you are willing to let Ruby actually load the file first, then you could ask Ruby after the fact:
require 'rubygems'
$LOADED_FEATURES.grep /\/rubygems\./