Archive for September 26th, 2006
A better rubygems lister
I’m in the process of teaching myself ruby - first by dealing with the language core and stdlib by just writing ruby (no frameworks) to replace my myriad of crappy shell scripts that I’m using for various things. I can do a lot more quickly in a ruby (or perl or even php) than I can in any of the shell languages. And it’s a great way to learn ruby.
One of the first things I’m doing is fixing a huge annoyance I have with rubygems - namely that the
gem list
command has no terse output. A standard gem list gives you something like:
*** LOCAL GEMS ***
actionmailer (1.2.5)
Service layer for easy email delivery and testing.
actionpack (1.12.5)
Web-flow and rendering framework putting the VC in MVC.
actionwebservice (1.1.6)
Web service support for Action Pack.
.
.
.
And I could give a flying rip what each does after I’ve read the descriptions the first time. So I’m taking advantage of a cool thing in rubygems - that it’s a modular library implemented as a rubygem itself - and reverse-engineering things a bit with it to give me something like:
$ ./gemver.rb actionmailer: 1.2.5 actionpack: 1.12.5 actionwebservice: 1.1.6 . . .
Here’s what I ended up with:
require 'rubygems'
if ARGV[0] then
@searchgem = ARGV[0]
else
@searchgem = ''
end
# get full local list of gems
@gemversions = {}
searchresult = Gem::cache.search(@searchgem)
# walk through returned gemspecs and build a hash of found gems and version(s) in GEM::Version format
searchresult.each{
|gemspec|
if @gemversions.key?(gemspec.name) then
@gemversions[gemspec.name].push(gemspec.version)
else
@gemversions[gemspec.name] = [gemspec.version]
end
}
# walk through the hash and print out the results
@gemlist = @gemversions.keys.sort
@gemlist.each{|gemname|
if @gemversions[gemname].size <= 1 then
print "#{gemname}: ",@gemversions[gemname][0].to_s,"\n"
else
# for gems with multiple versions, sort the versions in reverse order, GEM::Version implements a sort_by method
print "#{gemname}(multiple): "
versionsarray = @gemversions[gemname].sort_by { |arrayitem| arrayitem.version }.reverse
printlist = []
versionsarray.each{|eachversion| printlist.push(eachversion.to_s)}
print printlist.join(",")
print "\n"
end
}
Not completely bad for only my third day or so poking at ruby for replacing my system/service scripts (I’m actually using this in a comprehensive script to mail me periodic information about the configuration for each of my servers. This is actually an offshoot of a script to compare installed gems with a expected list of gems and versions - which I’ll post later)