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