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.:
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
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:
At the time of writing 0.9.0 is the latest version; using
wget you might do this:
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
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
/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
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
lib in the directory you created in step 1.1. You should also find new directories along the lines of
specifications 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
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.:
2.7. Do already have
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_PATHcontrols 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
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.
GEM_PATH is the key when reading
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:
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.
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
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 set
GEM_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.
If you are attempting to do a local-only install of multiple dependent gems, you need to cd to the directory containing the gems.