Ramble On

Rambles of a University Systems Manager

A better rubygems lister

without comments

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)

Written by jayoung

September 26th, 2006 at 11:31 pm

Posted in Uncategorized

Tagged with ,