[QUIZ] Where the Required Things Are (#175)

M

Matthew Moss

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Quiz 2:

1. Please do not post any solutions or spoiler discussion for this
quiz until 48 hours have passed from the time on this message.

2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A
permanent, new website is in the works for Ruby Quiz 2. Until then,
please visit the temporary website at

<http://splatbang.com/rubyquiz/>.

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem
helps everyone on Ruby Talk follow the discussion. Please reply to
the original quiz message, if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Where the Required Things Are (#175)

Occasionally, I've taken a look at the source for some Ruby module,
often because there is no manual or man page, or what documentation is
available is outdated or incomplete. Or sometimes I just want to see
how some Ruby stuff is implemented.

One such example was from the previous quiz: I want to learn more
about the Sys::Uptime module. I have it installed, and the call to
`require 'sys/uptime'` works, but I don't know how to use it. But,
alas, I also don't know where the installed files are located. The
shell command `which` doesn't help here, since the module is unlikely
to be in the shell's executable path.

What I would like is a script that works like `which` but for Ruby
modules. Examples:
ruby modwhich.rb "sys/uptime"
require 'sys/uptime' =>
/opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin8.11.1/sys/uptime.bundle
ruby modwhich.rb date
require 'date' => /opt/local/lib/ruby/1.8/date.rb

For extra credit, preserve this behavior when modwhich.rb is the main
program, but slightly different behavior is modwhich.rb is required by
another script:
ruby -r modwhich upsince.rb

require 'sys/uptime' =>
/opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin8.11.1/sys/uptime.bundle
require 'date' => /opt/local/lib/ruby/1.8/date.rb
Last reboot: 2008 Aug 22 at 18:49

Note that we allow upsince.rb to run as normal; the output of
modwhich.rb is mixed into stdout.
 
M

Matthew Moss

I think I'm gonna keep that around, looks useful to me.

You're not the first person to say that.

It would probably be useful, all around, to squish a couple of these
solutions together into a nice feature set and make a gem or rubyforge
pkg out of it.
 
E

Erik Hollensbe

Matthew said:
You're not the first person to say that.

It would probably be useful, all around, to squish a couple of these
solutions together into a nice feature set and make a gem or rubyforge
pkg out of it.

A require wrapper would be pretty slick:

module Kernel
def wrap_require(method=nil)
if block_given?
@@require_wrapper = block.to_proc
else
@@require_wrapper = method
end
end

@@old_require = method:)require)

def require(*args)
res = @@old_require.call(*args)
@@require_wrapper.call(*args) if (@@require_wrapper and res)
return res
end
end

Dunno if it really warrants a gem though. Maybe a snippet?

-Erik
 
A

Adam Shelly

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Quiz 2:

What I would like is a script that works like `which` but for Ruby
modules. Examples:
Here's my solution. I used the mod_req_level counter to restrict the
output to the files required at the top level. Without it, requiring
rubygems prints the rubygems location about 9 times.
-Adam

alias :eek:riginal_require :require

$mod_req_level=0
$mod_req_exts = %w{rb rbw o so dll bundle sl jar}.map{|ex| Regexp.new
"\.#{ex}$"}

def require lib
$:.each{|d| files=Dir.glob(d+"/#{lib}*")
f=files.find{|f|$mod_req_exts.find{|re|re=~f}}
(puts "require #{lib} => #{f}";break) if f
} if 1==($mod_req_level+=1)
begin
original_require lib
ensure
$mod_req_level-=1
end
end

if __FILE__==$0
ARGV.each{|f| require f}
end
 
D

Dan Stevens (IAmAI)

[Note: parts of this message were removed to make it a legal post.]

I've had a go at a solution, but I don't think what I did works properly.
Feel free to comment on what's wrong with it.


RUBYGEMS = 'rubygems.rb'

# Create a copy of the load path ($:)
@load_path = Array.new($:)

# Replace '.' in @load_path with full directory path
@load_path[@load_path.index('.')] = Dir.pwd

# Enforcing the require of rubygems before aliasing Kernel#require makes
things
# less troublesome.
begin
# If rubygems has been loaded, append the its path(s)
@load_path.concat(Gem.path) if require RUBYGEMS
rescue LoadError
# A LoadError will occur if rubygems isn't installed, but it should be
safe
# to ignore.
end

module Kernel
alias :eek:ld_require :require

# Make our own require method that uses '@load_path' variable to find
the path
# of the file given by 'string'
def require(string)
old_require string

# If 'string' doesn't have an extension
if File.extname(string).empty?
exts = ['.rb', '.so', '.o', '.dll']
until exts.empty?
fname = string + exts.shift
path = @load_path.find { |i| File.exists? File.join(i,
fname) }
return File.join(path, fname) unless path.nil?
end
else
return @load_path.find { |i| File.exists? File.join(i, string) }
end
raise "If you can read this, Kernel#require was able to find a
library " +
"named #{string} but #{__FILE__} was not able to. Either
there is" +
"bug in #{__FILE__} and/or Kernel#require's search method is
" +
"different to #{__FILE__}'s"
end
end

if $0 == __FILE__
ARGV.each { |a| puts require(a) }
end


2008/8/29 Matthew Moss said:
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Quiz 2:

1. Please do not post any solutions or spoiler discussion for this
quiz until 48 hours have passed from the time on this message.

2. Support Ruby Quiz 2 by submitting ideas as often as you can! (A
permanent, new website is in the works for Ruby Quiz 2. Until then,
please visit the temporary website at

<http://splatbang.com/rubyquiz/>.

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem
helps everyone on Ruby Talk follow the discussion. Please reply to
the original quiz message, if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Where the Required Things Are (#175)

Occasionally, I've taken a look at the source for some Ruby module,
often because there is no manual or man page, or what documentation is
available is outdated or incomplete. Or sometimes I just want to see
how some Ruby stuff is implemented.

One such example was from the previous quiz: I want to learn more
about the Sys::Uptime module. I have it installed, and the call to
`require 'sys/uptime'` works, but I don't know how to use it. But,
alas, I also don't know where the installed files are located. The
shell command `which` doesn't help here, since the module is unlikely
to be in the shell's executable path.

What I would like is a script that works like `which` but for Ruby
modules. Examples:
ruby modwhich.rb "sys/uptime"
require 'sys/uptime' =>
/opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin8.11.1/sys/uptime.bundle
ruby modwhich.rb date
require 'date' => /opt/local/lib/ruby/1.8/date.rb

For extra credit, preserve this behavior when modwhich.rb is the main
program, but slightly different behavior is modwhich.rb is required by
another script:
ruby -r modwhich upsince.rb

require 'sys/uptime' =>
/opt/local/lib/ruby/vendor_ruby/1.8/i686-darwin8.11.1/sys/uptime.bundle
require 'date' => /opt/local/lib/ruby/1.8/date.rb
Last reboot: 2008 Aug 22 at 18:49

Note that we allow upsince.rb to run as normal; the output of
modwhich.rb is mixed into stdout.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top