leah blogs

August 2008

08aug2008 · Taming $RUBYLIB with the Z shell

Ok, I’m fed up. Writing a good package manager for Ruby is a fight against windmills.

So let’s do the easiest thing that could possibly work. Redefining Kernel#require is a no-go, for it will lead to the gates of hell. Installing multiple projects to the same location is error-prone, requires non-trivial amounts of code and introduces packaging effort.

Luckily, most packages these days run directly from a checkout or their released archives (and if you provide neither, you’re doing it wrong). Essentially, all you need to make it convenient setting and manipulating $RUBYLIB, “A colon-separated list of directories that are added to Ruby’s library load path ($:).” The Z shell (1, 2) to the rescue!

Add this to your .zshrc (or .zshenv, if you want it in non-interactive shells as well):

# unique, exported, tied array of $rubylib to colon-seperated $RUBYLIB
# 08aug2008  +chris+
typeset -T -U -gx -a RUBYLIB rubylib ':'
rubylib-add()   { rubylib+=("$@") }
rubylib-del()   { for i ("$@") { rubylib[(r)$i]=() } }
rubylib-reset() { rubylib=(); [[ -f ~/.rubylib ]] && source ~/.rubylib }
rubylib-reset

This creates a zsh array rubylib which value reflects $RUBYLIB and vice versa (zsh does the same for $PATH and $MANPATH, for example), and defines three functions to add and remove paths as well as reset the variable.

Also, create a file ~/.rubylib where you set the defaults. I simply use:

rubylib-add ~/projects/{testspec,bacon,rack}/lib
rubylib-add ~/src/{camping,markaby}/lib

Remember, you can use the full power of zsh to set this:

rubylib-add ~/src/rubystuff/*/(lib|ext)(/)

You need to use (x|y) instead of {x,y} here to only expand to existing files. The final (/) ensures these files really are directories.

Reload your .zshrc, and voila, your packages are accessible from every Ruby script. Now, if a project has different requirements, just create a script there to adjust $RUBYLIB. Or use vared to interactively change the load path.

[Thanks to et for improving rubylib-del.]

NP: Curve—Dirty High

Copyright © 2004–2022