Tutorials

These are tutorials which show how to use the various features of GemInstaller. They are mostly brief, only showing the commands you need to type.

If anything is unclear, or if you’d like to see a tutorial on a topic, please submit a request on the mailing list.

Installing GemInstaller

$ gem install geminstaller
   - OR, if you get a permission error -
$ sudo gem install geminstaller 

See also: Docs on installation.

Bootstrapping your GemInstaller Config with the --print-rogue-gems option

You may have no idea what gems your app uses, or you might just want to create a GemInstaller config file with all the gems currently on your system, in order to install the same gems on a different system. This tutorial will show you how to use the --print-rogue-gems option to automatically create a GemInstaller config file.


$ geminstaller --print-rogue-gems > geminstaller.yml

That was easy, wasn’t it? This config file should specify the exact versions for all of the gems which are currently installed on your system.

Gotchas/Notes:

  1. If you generated the file on a unix/mac system with compiled gems and then try to run it on a different platform (like windows) which does not have a compiler, you may get errors. The prefer_binary_platform config property (deprecated) will try to guess at the correct platform, but if a binary version of the gem does not exist for your platform, or if prefer_binary_platform fails to guess the right platform, you may still fail.
  2. The --print-rogue-gems option generates exact version specifications. This means that you won’t ever get any gem upgrades by running GemInstaller with the standard generated file. This may be good (an upgrade can never break your app unexpectedly). However, you may wish to modify some of the version specifications to allow for upgrades. If you do this, remember to set the check_for_upgrade config property to true, but be aware that this will cause GemInstaller to check the remote gem server for upgrades each time it runs, and cause it to run slow or fail if the server is unavailable.

See also: Docs on --print-rogue-gems option, check_for_upgrade config property, and prefer_binary_platform config property (deprecated).

Using the autogem Option to Automatically Require Gems option

GemInstaller can automatically run the RubyGems ‘gem’ or ‘require_gem’ method to automatically add all of the gems in your GemInstaller config file(s) to the load path. Here’s an example.

First, create a simple geminstaller.yml file:

---
gems:
- name: ruby-doom
  version: '= 0.8'

Now, we’ll use irb to test autogem, and verify that it can add the ruby-doom gem to the load path:


$ irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'geminstaller'
=> true
irb(main):003:0> GemInstaller.autogem('--config=geminstaller.yml')
=> autogem returns the gem object(s) as it's return value...
irb(main):004:0> $: # Now verify the gem was added to the load path
=> ["/usr/local/lib/ruby/gems/1.8/gems/ruby-doom-0.8/lib", ...]

Note that autogem takes arguments in the same format as the GemInstaller command line and run method, but it ignores arguments which are not applicable (such as -r or -s). You could also specify no argument at all if you wanted to simply use the default geminstaller.yml file in the current directory. If you don’t want a certain gem to be loaded, you can set the no-autogem property to true for that gem in your config file.

You can also put a call to autogem during your application startup to automatically load all the correct gem versions which are specified by your config file. See Integrating GemInstaller into Ruby on Rails for an example.

See also: Docs on Automatically Requiring Gems with the autogem Method

Integrating GemInstaller into Ruby on Rails

RAILS 2.0 UPDATE:

I’ve created a Sample Rails App in the source, which shows how to use the Rails 2.0 config/preinitializer.rb hook. I need to spend some time updating the docs to reflect this, but for now just check out the source

OLD RAILS 1.0 INSTRUCTIONS:

GemInstaller can be configured to automatically install all gems in the config file, and add them to the load path when Rails boots. This means that you can check out and run your application anywhere, without having to worry about manually ensuring that the required dependency gems are installed. This works with Webrick and Mongrel.

First, you need a Rails app. I’ll let you handle this step on your own. See the Rails documentation for details.

Next, you need a geminstaller.yml config file. Create this under the Rails config directory. For details, see the documentation on the config file and the tutorial on bootstrapping your GemInstaller config with the --print-rogue-gems option. Here’s an example config which contains only entries for Mongrel and Rails, and ruby-doom:

RAILS_ROOT/config/geminstaller.yml:

  ---
  defaults:
    install_options: --include-dependencies
  gems:
  - name: ruby-doom
    version: '= 0.8'
  - name: rails
    version: '= 1.1.6'
  - name: mongrel
    version: '= 1.0.1'
    platform: <%= RUBY_PLATFORM =~ /mswin/ ? 'mswin32' : 'ruby'%>

Once you have your geminstaller.yml created, the last step is to add calls to GemInstaller.install and GemInstaller.autogem in your boot.rb. They should be placed right after the block which defines the RAILS_ROOT constant, as shown below (“…” indicates omitted lines):

RAILS_ROOT/config/boot.rb:

  ...
  unless defined?(RAILS_ROOT)
  ...
  end
 
  ############# Begin GemInstaller config - see http://geminstaller.rubyforge.org
  require "rubygems"
  require "geminstaller"
 
  # Path(s) to your GemInstaller config file(s)
  config_paths = "#{File.expand_path(RAILS_ROOT)}/config/geminstaller.yml" 
 
  # Arguments which will be passed to GemInstaller (you can add any extra ones)
  args = "--config #{config_paths}" 
 
  # The 'exceptions' flag determines whether errors encountered while running GemInstaller
  # should raise exceptions (and abort Rails), or just return a nonzero return code
  args += " --exceptions"
 
  # This will use sudo by default on all non-windows platforms, but requires an entry in your
  # sudoers file to avoid having to type a password.  It can be omitted if you don't want to use sudo.
  # See http://geminstaller.rubyforge.org/documentation/documentation.html#dealing_with_sudo
  args += " --sudo" unless RUBY_PLATFORM =~ /mswin/ 
 
  # The 'install' method will auto-install gems as specified by the args and config
  GemInstaller.install(args)
 
  # The 'autogem' method will automatically add all gems in the GemInstaller config to your load path, using the 'gem'
  # or 'require_gem' command.  Note that only the *first* version of any given gem will be loaded.
  GemInstaller.autogem(args)
  ############# End GemInstaller config
 
  unless defined?(Rails::Initializer)
  ...

This example also has configurable variables which illustrate the common option arguments you can control. The --exceptions argument will cause GemInstaller to raise an exception if errors occur, and thus abort Rails startup. The --sudo argument causes GemInstaller to be run via sudo.

Now, all you need to do is start Rails. You can use Webrick with ruby script/server, or Mongrel with mongrel_rails start. You should see the message from Geminstaller that the gems are being installed:

$ ruby script/server
GemInstaller is verifying gem installation: mongrel = 1.0.1, rails = 1.1.6, ruby-doom = 0.8
GemInstaller is automatically requiring gems: mongrel = 1.0.1, rails = 1.1.6, ruby-doom = 0.8
./script/../config/boot.rb:55:Warning: require_gem is obsolete.  Use gem instead.
=> Booting WEBrick...
GemInstaller is verifying gem installation: mongrel = 1.0.1, rails = 1.1.6, ruby-doom = 0.8
GemInstaller is automatically requiring gems: mongrel = 1.0.1, rails = 1.1.6, ruby-doom = 0.8
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2007-05-13 22:41:37] INFO  WEBrick 1.3.1
[2007-05-13 22:41:37] INFO  ruby 1.8.5 (2006-08-25) [i686-darwin8.7.1]
[2007-05-13 22:41:37] INFO  WEBrick::HTTPServer#start: pid=2519 port=3000

If that worked, good! If not, carefully read the error message. If it was a RubyGems failure (as opposed to a bug in GemInstaller), the “gem” command that GemInstaller tried to execute should be echoed as part of the error message. Cut and paste this command onto the command line, and see if you get the same error. If you do, then resolve it and the problem should go away under GemInstaller as well.

For extra credit, we can write a simple Rails controller to verify that the correct gems are getting added to the load path by the autogem command. First, create the Rails app and a controller:


$ rails geminstaller_example
$ ruby script/generate controller GemInstallerExample

Next, create the Rails app. You need…

…an action:
RAILS_ROOT/app/controllers/gem_installer_example_controller.rb


class GemInstallerExampleController < ApplicationController
  def index
  end
end

…a sample rhtml page which will show your config and load path:
RAILS_ROOT/app/views/gem_installer/index.rhtml


<% config = File.open(“#{RAILS_ROOT}/config/geminstaller.yml”)
config_lines = config.read.gsub!(“\n”,“
”) >


geminstaller.yml


<= config_lines >




Load Path:


<= $:.join(“\n”) %>




…a default route to your page:
RAILS_ROOT/config/routes.rb


  1. Put the following line as the first route in the routes.rb file:
    map.connect ’’, :controller => “gem_installer_example”

…a GemInstaller config file:
RAILS_ROOT/config/geminstaller.yml:

---
defaults:
  install_options: --include-dependencies
gems:
- name: ruby-doom
  version: '= 0.8'

…the modifications to boot.rb (comments and local variables omitted here for brevity):


unless defined?(RAILS_ROOT)

end

  1. Begin GemInstaller config – see http://geminstaller.rubyforge.org
    require “rubygems”
    require “geminstaller”
    config_paths = “#{File.expand_path(RAILS_ROOT)}/config/geminstaller.yml”
    args = “—config #{config_paths}”
    args += " —exceptions"
    args += " —sudo" unless RUBY_PLATFORM =~ /mswin/
    GemInstaller.install(args)
    GemInstaller.autogem(args)
  2. End GemInstaller config

unless defined?(Rails::Initializer)

…and delete the public/index.html file:


$ rm public/index.html

Now, you should be able to start the example Rails app and navigate to http://localhost:3000 to view your config file and load path with the gems auto-required:

$ ... cd to root of your rails app ...
$ mongrel_rails start

…open http://localhost:3000, and you should see something like this:


_____________________________
geminstaller.yml
/—-
defaults:
install_options: —include-dependencies
gems:
- name: ruby-doom
version: ‘= 0.8’
_____________________________
Load Path:

(lots of load path stuff omitted)

(here’s our gem!)
/usr/local/lib/ruby/gems/1.8/gems/ruby-doom-0.8/lib /usr/local/lib/ruby/gems/1.8/gems/sources-0.0.1/bin


(more stuff omitted)

That’s about it!

See also: Docs on Using GemInstaller with Ruby on Rails or Other Ruby Apps.

Using Common or Shared Config Files or Snippets

GemInstaller supports multiple config files, with the last config files in the list overriding the previous ones. It also supports the include_config property in the geminstaller.yml file, which allows you to share a YAML snippet across multiple config files. This means you could do any of the following:

  • With multiple config files:
    • Have a common config file across all your projects, which is shared via an svn:external, and a custom config file to override or add gems which are not in the common config.
    • Have a common config file across all development machines, shared on a windows share or NFS mounted drive, with machine- or platform-specific gems listed in local config files.
    • Have config files that are specific to certain environments such as development and test, which will not be included when GemInstaller is run in a demo or production environment.
  • With the include_config property:
    • Shared YAML snippets across multiple geminstaller.yml files via an svn:external.
    • Extract geminstaller.yml entries that are duplicated across multiple files to a single shared include snippet file.
    • Use a common include to simultaneously upgrade to the same version of a gem dependency across multiple projects.
    • Extract complicated or shared ERB logic in geminstaller.yml (such as automatically determining the correct version of a gem based on an environment variable) into a separate file.

TODO: Finish writing examples of this, for now see docs on the --config option.

See also: Docs on the --config option, Docs on the include_config property.

Running GemInstaller from Capistrano

GemInstaller can be hooked in as a capistrano task. This is a way to avoid having gems installed via the preinitializer.rb run in demo or production, and possibly cause problems with app startup in these environments (note you still want to Activate them in preinitializer.rb via GemInstaller.autorun). It also is a way to avoid the current bug with Rails and Mongrel gems not being loaded correctly if they are upgraded during the app startup process. Here’s an example recipe:


namespace :deploy do
  desc "gem installer"
  task :geminstaller, :roles => :app do
    sudo "geminstaller -c #{current_release}/config/geminstaller.yml"
  end
end

See also: Docs on Using GemInstaller from Other Ruby Apps.

Running GemInstaller from Vlad the Deployer

You can also run GemInstaller from Vlad the Deployer. Check out this gist and blog post from John Dewey . Here’s the contents of that gist:


### lib/tasks/app.rake
 
begin
  require 'vlad'
  Vlad.load :scm => :git, :web => :apache
rescue LoadError
  puts $!
end
 
### Extending 'vlad:update' with 'gems:geminstaller'
namespace :vlad do
  desc "Install gems via geminstaller."
  remote_task :update, :roles => :app do
    Rake::Task['gems:geminstaller'].invoke
  end
end
 
namespace :gems do
  desc "Run geminstaller."
  remote_task :geminstaller, :roles => :app do
    run "geminstaller --sudo -c #{current_path}/config/geminstaller.yml"
  end
end