HowToUseMultipleGemRepositories
The gem utility is a handy way to manage software components in Ruby. When using Rails, though, you can sometimes find yourself in a position where gems might start to look like a handicap!
- Perhaps you are installing a Rails application on a managed host account and it needs a gem which the system administrator does not support.
- Perhaps you’re a system administrator and you want to allow individual users to add their own gems, without polluting the global collection you provide centrally.
- Perhaps you just want individual Rails applications to have their individual requirements kept separate from each other to avoid Ruby’s own equivalent of DLL Hell…!
As it happens, it’s entirely possible to support more than one physical gem repository. The key to this is the GEM_PATH
environment variable. While the GEM_HOME
environment variable is relatively well known, not so many people have heard of GEM_PATH
. Below I’ll describe how to use this to configure and initialise a new gem repository, then logically, but not physically combine that new collection with other existing repositories which Ruby code will treat as one large, combined set of available gems.
1. Decide on locations
1.1. A new gem installation
You’ll need to install a new copy of the gem utility, at least temporarily. Create an empty ‘geminstall’ directory to hold the gem installation itself – e.g.:
mkdir /home/username/ruby/geminstall
1.2. Location of the new repository
Create an empty directory to hold the gem repository (that is, the location where any gems you install will actually live) and set GEM_HOME to this location – e.g. assuming a bash
shell:
mkdir /home/username/ruby/gems export GEM_HOME=/home/username/ruby/gems
2. Initialise the new repository
2.1. Get the gem installation package
Download the gem installation package from:
http://rubyforge.org/frs/?group_id=126
At the time of writing 0.9.0 is the latest version; using wget
you might do this:
wget
http://rubyforge.org/frs/download.php/11289/rubygems-0.9.0.tgz
2.2. Unpack into a temporary directory
Create a directory for temporary use and unpack the archive into it. For example:
mkdir /home/username/temp mv rubygems-0.9.0.tgz /home/username/temp cd /home/username/temp tar -z -x -f rubygems-0.9.0.tgz
2.3. Look at the unpacked contents
Change into the unpacked directory so you can see the CHANGES
, README
etc. files. E.g.:
cd rubygems-0.9.0 ls
2.4. Ask the setup program to install everything, make sureGEM_HOME is set to the gems directory from step 1.2
Issue the following command:
ruby setup.rb all --prefix=/home/username/ruby/geminstall
…replacing /home/username/ruby/geminstall
with the path to the ‘geminstall’ directory that you created in step 1.1 (and not the one you created in step 1.2!). The command should finish up by saying something like Successfully built Rubygem
, with a bit more information on what it built afterwards. If not, look for error messages and see if you can figure out what went wrong (e.g. perhaps there were no write permission in the gem installation or repository directories, or maybe you have an incorrectly set GEM_HOME
– double-check it with echo $GEM_HOME
).
NOTE: If you already have rubygems installed, make sure the version you are installing matches the version you have installed (or upgrade your existing rubygems first). Otherwise you may run into strange errors due to mismatched files.
2.5. Make sure it worked!
You should find new directories along the lines of bin
and lib
in the directory you created in step 1.1. You should also find new directories along the lines of cache
, doc
, gems
andspecifications
in the directory you created in step 1.2. This is your new gem repository, now initialised and ready for further use.
NOTE: If you receive the message “/gem:9:in `require’: no such file to load — rubygems”, you will have to set the RUBYLIB environment variable to point to the ‘lib’ directory inside your gem install directory, like so: export RUBYLIB=/home/username/ruby/geminstall/lib
2.6. Don’t already have gem
installed?
If you don’t already have gem installed on your system you will want to add the path to the directory specified in step 1.1 with /bin
on the end to your PATH
environment variable. E.g.:
export PATH=$PATH:/home/username/ruby/geminstall/bin
2.7. Do already have gem
installed?
If you do already have a copy of gem on the system, now would be a good time to delete the ‘geminstall’ directory you created in step 1.1, along with its contents. You don’t need the second copy of the gem package, you only need the ‘gems’ repository directory. So:
rm -rf /home/username/ruby/geminstall
…taking care to provide the full path to the location of the unwanted new gem installation (geminstall) from step 1.1, not the path to the new gems repository from step 1.2.
3. Examining the repository contents
3.1. What do the GEM_...
variables do?
While environment variable GEM_HOME
controls where gem will write things, variable GEM_PATH
controls from where gem
and requirements in Ruby scripts will read.
3.2. Querying the default repository
If you issue the command gem query
with GEM_PATH
unset you’ll see the list of gems installed in your system default repository, if you have one, not your new repository.
3.3. Querying your new repository
Set GEM_PATH
to the ‘gems’ directory you created in step 1.2 then query the repository again:
export GEM_PATH=/home/username/ruby/gems gem query
This time you should just now see one gem – the sources installed as part of repository initialisation in step 2.4.
3.4. GEM_PATH
is the key when reading
So, GEM_PATH
is the key to supporting multiple repositories. To treat multiple physical repositories as one big logical gem collection, set the variable to a colon-separated (semi-colon on windows) list of repository locations. For example, if you have a system-wide default repository at/lib/ruby/gems/1.8
you can get Ruby to search your new repository first, then the system one, using:
export GEM_PATH=/home/username/ruby/gems:/lib/ruby/gems/1.8
If you have two or more of the same gems with the same version, the one in whichever repository appears first in the path will be used. It shouldn’t ever matter, though, as if they’ve the same version number they ought to be identical anyway.
3.5. PATH
to gem binaries
You need to add the new gem repositories bin sub-folder to the PATH environment variable in front of the default gems repository bin path otherwise any new gems installed in this repository will not have their bin wrappers in the path and you will not be able to run them as you normally would from the command line. For example, if you installed a gem like piston in this new repository a small shell script or batch file will be put in the repositories bin folder so that you can launch the piston script by simply typing ‘piston’, but the shell script or batch file will not be found if the bin folder is not in the path.
4. Modifying the new repository’s contents
4.1. GEM_HOME
for writing, GEM_PATH
for reading!
Always ensure that environment variable GEM_HOME
points to the
repository you are interested in before running the gem
command to modify a repository, or any other commands that modify the contents of a repository. This is very important! If the variable is unset, you’ll operate on the system’s default gem repository.
4.2. Business as usual
Once you’ve set GEM_HOME
to point to the right place, just use gem
in the usual fashion to delete or add new gems – see the RubyGems Manuals for more information.
If you want to make a quick repository change and just temporarily set the location, gem
supports various command line switches to help. For example:
gem install [gem-name] --install-dir=/path/to/repository
…will do what the command implies. Depending on how you work this might be a better method than setting the environment variable. However, if you take the environment variable approach, there’s no danger of forgetting to specify the repository location on the command line and ending up accidentally attempting an operation in the wrong place. Again, see the RubyGems Manuals for more information on command line parameters.
5. Using the repositories in future
You will need to make sure GEM_PATH
is set up wherever you want Ruby programs, including Rails applications, to use multiple gem repositories. The best place to do this will vary depending on your system configuration. Use, say, your .bashrc
file or the Web server configuration file for Rails applications if it supports launching them with a configured private set of environment variables.
That’s it – all done. Remember to set GEM_HOME
when adding or removing items; remember to setGEM_PATH
when reading from one or more repositories. Now you can keep your gem collections compartmentalised if you wish, provide individual repositories for individual users, or if you’re on a rather limited managed hosting service, have a good chance of being able to add your own gems to a private collection without needing to go to the system administrator.
Note
If you are attempting to do a local-only install of multiple dependent gems, you need to cd to the directory containing the gems.
No comments:
Post a Comment