Thursday, February 26, 2009

HowToUseMultipleGemRepositories -- Rescued!


Note:  My intent here is not to plagarize, only to save lost content.  This information was posted on the rails wiki, but it's gone!  It was here: 


It looks like the whole wiki has been redone, so if anyone knows where this info has been reposted, please let me know.  I did a quick search, but didn't find it, and don't have time right now to hunt...    This is great information, and it shouldn't be lost, so I'm grabbing a cached copy, and putting it here.  So, with thanks to those who created the content, here it is:

-------------------------------------------------------------------------------

Ruby on Rails
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 CHANGESREADME 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 cachedocgems 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_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

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