Making it easier to install gems on Windows

Posted by Brian in Rails, snacks (July 12th, 2007)

Update 2009-11-15 This is out of date. There’s no reason to read further. Rubygems does OS detection automatically now.

When you install gems, you’re usually asked what version you want to install. Windows users have to choose the one that says ‘mswin32’. This can be really, really awkward for people who are new to this. You have to admit that this is confusing for a first-time Rails on Windows user:

Select which gem to install for your platform (i386-mswin32)
 1. mongrel 1.0.1 (mswin32)
 2. mongrel 1.0.1 (ruby)
 3. mongrel 1.0 (mswin32)
 4. mongrel 1.0 (ruby)
 5. Skip this gem
 6. Cancel installation

I’ve had lots of students say that they thought they should choose the Ruby one because that’s what they’re programming in.

I found a great example at by Todd Fisher that explained how to skip the os and version selection on Linux, so I modified it slightly to work with Windows and I’ve added my own method to make installation of gems easier for Windows users.

Here’s how it works: You install gems via a new command on Windows to skip selection of OS and version number.
This will install the gem with dependencies, without documentation. I made the choice to skip doc generation because it’s much faster, but you can modify the script below to take that out, or even make it optional, based on parameters you pass in.

Examples of use:

   gem_install rails
   gem_install rails mongrel mongrel_service capistrano redcloth tzinfo zentest rcov

Here’s the source code for the file. Save this to c:\ruby\bin\gem_install.bat or anywhere on your PATH. source code:

@echo off
goto endofruby

# Cobbled together by Brian Hogan from scripts found at
# and by Todd Fisher.
# Many thanks to their hard work for their solutions that finally made this possible.

    require 'rubygems'

    # Patch gems to only install the latest Windows version of the gems.
    Gem::RemoteInstaller.class_eval do
      alias_method :find_gem_to_install_without_ruby_only_platform, :find_gem_to_install
      def find_gem_to_install( gem_name, version_requirement, caches = nil )
        if caches # old version of rubygems used to pass a caches object
          caches.each {|k,v| caches[k].each { |name,spect| caches[k].remove_spec(name) unless spec.platform == 'ruby' } }
          find_gem_to_install_without_ruby_only_platform( gem_name, version_requirement, caches )
          Gem::StreamUI.class_eval do
            alias_method :choose_from_list_without_choosing_ruby_only, :choose_from_list
            def choose_from_list( question, list )
              result = nil
              result_index = -1
              list.each_with_index do  |item,index|
                if item.match(/\(mswin32\)/)
                  result_index = index
                  result = item
              return [result, result_index]
          find_gem_to_install_without_ruby_only_platform( gem_name, version_requirement )
    # end patching of Gems.


    # Install multiple gems with dependencies and without documentation.
    # pass in an array of gem names to install.
    #   install_gems "mongrel", "redcloth", "mongrel_service", "tzinfo", "capistrano"
    def install_gems(*attrs)
        puts attrs.inspect
        attrs.each do |gem_name|
            puts "installing gem #{gem_name}"
            Gem::['install', gem_name, '--include-dependencies', '--no-rdoc', '--no-ri'])

if ARGV[0] == "help"
  puts "Install gems via this tool on Windows to skip selection of OS and version number.  This will install the gem with dependencies, without documentation."
  puts "Examples:"
  puts "   gem_install rails"
  puts "   gem_install rails mongrel mongrel_service"
  puts "Report bugs to ."
    install_gems ARGV


"ruby" -x "%~f0" %*

That’s it. It works great so far and I’m going to be embedding this into the Eclipse for Rails installation. You Mac users should have no trouble taking this concept to your platform. It just involves changing the regex from mswin32 to ruby in the Ruby portion of the script and then copying the Ruby code into its own .rb file that you mark executable.

I should say something about how the whole thing works. When you run the batch file, it skips over the Ruby code because of the goto command and then actually passes itself to the Ruby interpreter.

   ruby -x gem_install.bat rails mongrel

The additional parameters you send to the batch file are also passed along to the Ruby script as well. The Ruby interpreter ignores everything in the file until it gets to the shebang line (#!/bin/ruby). It starts executing code from this point on, but then it stops when it gets to __END__. Everything else in the file is ignored.

This method is how we Windows users get to do things like rake or gem or even rails Linux users can just set a Ruby script to be executable. Windows users have a little more trouble doing that so we cheat.

Before I go, I should say that I could not have done this without Curt Hibbs, who uses this batch-file-to-ruby approach in the One-Click Ruby Installer. He’s a swell guy.

If you’ve got comments, I’d love to hear them. Let me know what you think, or if there are ways I can improve this.

2 Responses to ' Making it easier to install gems on Windows '

Subscribe to comments with RSS or TrackBack to ' Making it easier to install gems on Windows '.

  1. about2flip said,
    on October 31st, 2009 at 2:24 pm

    Where do I place the gems I need to install?

  2. Brian said,
    on November 15th, 2009 at 6:49 am

    You shouldn’t have to place any gems anywhere. And this article is out of date. To install gems on Windows now all you need is the One Click Ruby Installer, then open command prompt and type gem update –system and then gem install rails mongrel sqlite3-ruby

Leave a reply

:mrgreen: :neutral: :twisted: :shock: :smile: :???: :cool: :evil: :grin: :oops: :razz: :roll: :wink: :cry: :eek: :lol: :mad: :sad: