RICHARD FAWCETT'S WEBSITE

ABOUT     CONTACT     RSS


8 October 2010
Installing Ruby for MongoDB Use on Windows

I've recently downloaded the first three chapters of Kyle Banker's "MongoDB In Action" from Manning's early access program.  So far, it's shaping up to be a great read.  In it, Banker uses Ruby in his examples, and the MongoDB project provide an official Ruby driver to access MongoDB.  Now, I'm pretty much a C# person through and through these days, but the C# driver for MongoDB is not officially supported.  So, I decided to install Ruby so I could follow along with the examples in the book.  Getting to a situation where everything just worked was a long, painful process, and I'd like to share my findings so others don't have to go through the same frustrations.

Getting and Installing MongoDB

This was the easiest part of the operation, despite Appendix A of the book (installing MongoDB) having not been written yet.  MongoDB can be downloaded from http://www.mongodb.org/downloads.  If you have a 64-bit operating system, it's really worth getting the 64-bit version, as the 32-bit version can only address around 2GB of data.  MongoDB comes as a .zip file.  At the time of writing, the latest stable release was version 1.6.3, which is what I got.

I unzipped this file into "C:\Program Files" and then renamed the uncatchy folder mongodb-win32-i386-1.6.3 to plain old "MongoDB".  Next, I added "C:\Program Files\MongoDB\bin" to the path environment variable.

The final installation step is creating a folder for MongoDB to store its data.  I created the folder "C:\MongoDBData" for this purpose.

Testing MongoDB

To start MongoDB, I typed the following at a command prompt:

mongod.exe --rest --dbpath c:\MongoDBData

The command prompt shows some status information telling me that the server is listening on port 27017 and the admin web interface is listening on port 28017.  The --­­rest command line parameter is optional, but does seem to enable some more advanced features on the web interface, which I'm not going to cover here.

Now, to test MongoDB, I ran the Mongo client by simply executing the command "Mongo".  In its interactive shell, I entered the commands:

use testdb
db.foobar.save({foo: "bar"})
db.foobar.count()
db.foobar.find()

The count command output "1" to the console, and the find command printed:

{ "_id" : ObjectId("4caf963d1a58000000001bbb"), "foo" : "bar" }

This article isn't a tutorial on MongoDB, but if you see something like that (your ObjectId will differ) then all is well.  Briefly, the code connects to the "testdb" database (creating it if it doesn't exist), then adds a new record to the "foobar" collection (creating it if it doesn't exist) and finally gets a count of rows in the collection and finally lists the row's data.  The "_id" field is automagically added by MongoDB and is the collection's primary key.

Getting and Installing Ruby and the Mongo Driver

Banker's book points the reader to http://ruby-lang.org/en/downloads to install Ruby and then to http://docs.rubygems.org/read/chapter/3 to install Rubygems.  That's what I did at first, and had all kinds of problems trying to install Rubygems, which is the package manager for Ruby.  As we'll see later, it's used to install optional packages such as the MongoDB drivers.

Instead of using Banker's URIs, I found the site http://rubyinstaller.org/downloads which seems more geared to the Windows user.  It explains that the RubyInstaller packages install both Ruby and Rubygems as part of the same install; no wonder I had problems trying to do a separate install of Rubygems.

So, from the rubyinstaller website, I downloaded and installed Ruby 1.9.2-p0.  To keep things simple, I decided to accept the default install path of "C:\Ruby192" and I also elected to add the Ruby executables to my path and to associate .rb and .rbw files with the Ruby installation.  I decided not to install into "Program Files" to avoid any spaces in the path name.  I'm not sure if this was necessary, but just thought I'd err on the side of caution.

Now, on your start menu, underneath the Ruby folder, you'll have a Command Prompt with Ruby icon.  I'm not sure what this does over and above a normal command prompt, but decided to use it, just to be sure.  At this command prompt, to install the MongoDB driver, I typed:

gem install mongo

After a worryingly long time with no visual feedback until completion (it took around a minute, just be patient!), gem successfully installed two gems… mongo, and its dependency bson.  BSON is a binary form of JSON, used by MongoDB to store its data and communicate over the network.

Testing Ruby and the Mongo Driver

The first thing I tried, was the ubiquitous "Hello, World!" program in Ruby.  I created a file called hello.rb and entered the following:

puts "Hello, World!"

I ran it by typing ruby hello.rb at a command prompt.  You guessed it… the output was "Hello, World!".  It works!

Now, more advanced… it's time to test out the Mongo driver. Ensure that the MongoDB server is still running (run it again if it's stopped).  I created a file called mongotest.rb and entered the following:

require 'rubygems'
require 'mongo'

@con = Mongo::Connection.new
@testdb = @con['testdb']['foobar']
puts @testdb.count()

@cursor = @testdb.find()
@cursor.each do |document|
  puts document["foo"]
end

These are effectively the same commands we entered at the MongoDB interactive shell earlier to test our database.  Execute the script using the command "ruby mongotest.rb".  The results returned should be the same as earlier… "1" and "bar".  This proves we connected ok. However, there was a warning message displayed first about needing the gem bson_ext for optimum performance.  A helpful message told me I could install it by typing "gem install bson_ext".  Sadly, it wasn't that easy.

Installing bson_ext gem

Some gems have prebuilt Windows executables which are simply downloaded by the gem package manager.  Some however, don't.  These must be downloaded as source and built locally.  As Ruby seems to be primarily a *nix oriented world, the gems require what is known as a "sane" environment in which to build.  This means access on the path to various *nix tools like gcc and make.  This being Windows, they're absent.

In fact, trying to execute "gem install bson_ext" gives an exception stack trace along with the message "The compiler failed to generate an executable file. (RuntimeError) You have to install development tools first."

So, after a fair bit of Googling / Binging (delete as appropriate), I found out that there is a development kit available which includes a good set of Unix build tools for just this purpose.  It's available again from http://rubyinstaller.org/downloads. The link I chose was DevKit-4.5.0-20100819-1536-sfx.exe.  The page http://github.com/oneclick/rubyinstaller/wiki/development-kit was an invaluable resource with detailed install instructions for the DevKit.  In short, the instructions are:

1. Run the downloaded executable (which is a self-extracting .zip file) and unzip to a path with no spaces in it.  I chose "c:\DevKit".

2. CD to the extract folder and run "ruby dk.rb init" to generate the file config.yml.

3. Check that config.yml contains the path to your Ruby installation.  If not, fix it up manually using the instructions in the comments in the .yml file.

4. Run "ruby dk.rb install" to tell Ruby to use the DevKit in future.

If everything worked, then executing

gem install bson_ext --platform=ruby

should install the bson_ext gem correctly.  I'm not sure what the platform=ruby argument is for, but the page at github.com recommend its use.

Now, rerun the command "ruby mongotest.rb" after using CD to get back to the directory your script is in.  This time, you should get the results "1" and "bar" without any warning messages.

Further Problems, Unrelated to MongoDB

As I read further into "MongoDB In Action", Banker uses the gem "sinatra" to create a simple web application.  Well, it turns out that sinatra doesn't yet work under Ruby 1.9.2 and an exception is thrown when running a script which uses sinatra.  It seems that there are (as yet unreleased) patches in the trunk to fix this bug, and instead of getting the gem "sinatra", it was suggested I instead download the gem "sinatra-sinatra" and specify a different repository to the default one.  However, this just seemed to move the problem further down the line and different errors were encountered.

In order to get around this problem with sinatra, I had to go back to an earlier version of Ruby, version 1.9.1-p430.  Once installed, I changed my path environment variable to point to this older version, and had to patch it with the DevKit again.  In my opinion, that the new version of Ruby breaks sinatra means that there is something seriously wrong with either Ruby or sinatra.

Summary

We've installed and tested MongoDB which was a relatively simple process.  Ruby proved not to be so simple.  My opinion is that Ruby is primarily designed for use in a *nix environment, and making it work on Windows can be a fine art.  While the instructions above seem relatively straight-forward, it took a fair bit of research to arrive at this "path of least resistance" to getting everything installed.

As I continued to explore Ruby and install additional packages, I encountered version incompatibilities; an Internet search suggests there may be many incompatibilities out there.  This is a real shame, and the community would be well-served to get this kind of problem sorted out.  These incompatibilities serve as a high barrier of entry for newcomers to Ruby like myself, and I nearly decided to give up before I'd really got started.

As the Kaiser Chiefs sang in their hit single Ruby: "Ruby, Ruby, Ruby, Ruby, Do ya, do ya, do ya, do ya, Know what ya doing, doing to me? Could it be, could it be, that you're joking with me, And you don't really see you with me."  Fitting, I thought.

I hope my findings are of some use to you, and that you enjoy your explorations into the world of Ruby.

From what I've seen so far of the book "MongoDB In Action", it's shaping up to be an excellent book, and well worth a read.