Getting Started with DataMapper on JRuby

Underneath DataMapper (at least if you haven't bitten the NoSQL bullet
just yet) lies DataObjects. DataObjects is an attempt to rewrite existing Ruby
database drivers to conform to one, standard interface. If you're a recent
arrival from the world of PHP or .Net, then the DO API will not look too
disimilar to either PDO or ADO.net.

Late this spring, tucked away in the DataObjects' Release Notes for version
0.9.12, was mention of support for JRuby. Unfortunately the support that
featured in 0.9.12 was incomplete at best. We needed a little longer to get
things working well, but over the summer we made significant progress in
supporting a large number of databases on the JRuby platform.

For a long while, I had a Gist up on Github illustrating the steps needed to get
up and running with DataMapper on JRuby. I promised to follow up with a more
detailed tutorial, but it's taken some time to get it published. In part, this
has been down to the fact that going through the process of writing a tutorial
has helped me uncover a plethora of bugs and inconsistencies, and I wanted to
take the time to deal with them before hitting the metaphorical "publish"
button. In any case, I hope this will be the first of many future Ruby postings.

For the purposes of this tutorial, I am using Merb as the MVC Framework,
but you should also be able to use Rails, Camping, or Sinatra.

Many thanks to Dan Kubb (dkubb) for looking over
this post and to George Adamson for actually
having the patience to test out these steps (on Windows, of all platforms!)

Preflight

Install Java and the JDK

If you are running a recent version of Mac OS X, you should already have both
the Java Runtime Environment and Java Development Kit (JDK). Apple supplies
their own set of Java tools (although the Soylatte implementation is
available if you want Java 6 on Tiger and Leopard 32-bit machines).

On Windows or a Linux distribution, you will likely already have the Java
Runtime Environment, but unless you've been doing Java development, you may be
without the JDK. The JDK is available from Sun's Java downloads page.

Install JRuby

We generally test against the latest stable version of JRuby. I've also tested
against v1.2.0, but I'd recommend being on 1.3.1 or 1.4.0. Installing JRuby
is as simple as downloading and decompressing the distributed .zip/.tar.gz
file (or running the new .exe installer, if you're on Windows).

Because these instructions rely on installation from source, we'll also be
compiling extensions that are written in Java. Hence make sure the JDK (and the
Java compiler, javac) are in your PATH:

c:\Users\alexbcoles>javac -version
javac 1.6.0_16

On Windows for example, this would mean adding C:\Program Files\Java\jdk1.6.0_16\bin
to PATH. Again, more verbose instructions can be found in the wiki.

Install DataMapper + Merb

A major requirement in developing DataObjects'/DataMapper's JDBC support was
parity in the installation procedure. Installing on JRuby should be just as easy
as for MRI / 1.9.

The good news is that if you want the latest published gems, you should be able
to install them as follows:

jruby -S gem install do_sqlite3 dm-core dm-more merb

That's it! Unlike with ActiveRecord, you don't have to specify a separate JDBC
variant.

However, for the purpose of these instructions and because our JRuby support is
still developing at a rapid pace (for instance, our SQL Server support is only
available in our Git repository), we'll cover installing the edge version of
DataObjects / DataMapper.

Install Pre-Requisites

Note: Under Windows Vista/7, if you've used the JRuby installer and have
your system gems directory in C:\Program Files\ then you may have to run
cmd.exe with Administrator privileges (Start -> type cmd.exe, right
click, Run as Administrator).

Note: On *NIX platforms, you may need to prefix commands with sudo,
depending on where you installed jruby (unless, of course, you're using
rvm).

Install Addressable and an implementation of JSON:

jruby -S gem install json_pure addressable

Install Jeweler (DataMapper and Merb projects are currently in the process of
migrating their Rakefiles to use Jeweler):

jruby -S gem install jeweler

Install Extlib

Change to the directory where you keep your Code. (So ~/Dev, c:\code,
c:\Documents and Settings\harry\Code, etc.)

Note: If the rake install task fails under Windows, try again in two steps:

jruby -S rake package
jruby -S gem install pkg\extlib-0.9.14.gem

Extlib is a collection of extensions to core Ruby classes and is currently used
by both the DataMapper and Merb projects. However, it'll go away in future
versions as we start to take advantage of the new, modular ActiveSupport in
Rails 3.0.

Install DataObjects

Next, decide on the driver for the database vendor you wish to use. If you're
installing from source, there will be three components to install:

do_jdbc: DataObjects' JDBC support library. This is a Java library,
packaged as a Jar, and then wrapped up as a RubyGem.

the JDBC driver: the database vendor's driver using the JDBC API. Also a Java
Jar, and in most cases, available wrapped up as RubyGems.

the actual DataObjects' driver: written in Java and relies on the above two
libraries at runtime. Compiled against do_jdbc.

To install do_jdbc (the DataObjects' JDBC support library):

cd do_jdbc
jruby -S rake compile
jruby -S rake install
cd ..

To install the JDBC driver for the DataObjects driver, if you're using one of
mysql, postgres, sqlite3 then we rely on ActiveRecord-JDBC to package the
JDBC jar files as Gems for us. Installation should be a matter of:

If you're on Oracle, then you need to place the Oracle JDBC driver ojdbc14.jar
in your Java load path. Read Raimond's blog article for more
instructions.

If you're on SQL Server, the ActiveRecord-JDBC has not yet packaged the jTDS
JDBC driver as a RubyGem. However, we have this available in the DataObjects
repository (you may need hoe first jruby -S gem install hoe):

cd jdbc_drivers/sqlserver
jruby -S rake install
cd ../..

Unless you've got your own project or have your mind set on a specific vendor's
relational database, then follow this tutorial all the way through and install
SQLite3 support (it means you won't have to do any configuration later!):

jruby -S gem install jdbc-sqlite3

Then you can proceed to install the DataObjects' driver:

cd do_[DBNAME]
jruby -S rake compile
jruby -S rake install
cd ../..

Install DataMapper

Installing DataMapper's core and more gems should then be very straight-forward:

Note: The next major version of Merb, 1.1, will completely replace the
dependency handling mechanism described here with Yehuda Katz's (wycats)Bundler. It's technically possible to use the Bundler with Merb 1.0.x
series, but for concision, I won't elaborate on doing that here.

Run Merb

Before adding in any customisations of your own, check you're able to run the
application.

Merb is built on Rack, and Rack needs a webserver. Webrick is a part of the Ruby
standard library, so we could use that:

jruby -S merb -a webrick

(the -a flag specifies an adapter)

I encountered problems shutting down Webrick though, and had to kill it.
Additionally, you'll probably want to use the server you'll end up deploying to,
so let's try with Mongrel instead:

jruby -S gem install mongrel
jruby -S merb -V

(this time with -V to give us some verbose output)

I am personally a big fan of GlassFish for Java/JVM deployments.
You can use something like Warbler to create a WAR file for deployment, but if
you're coming from the Ruby world, the following is much simpler:

jruby -S gem install glassfish
glassfish

Add a Model

Here I start to get lazy. Bereft of ideas, and starting to think about needing
to cook, I decided to create a simple Recipe tracker. While introducing some of
the cooler (and defining) DataMapper features will have to wait until a future
article, this simple child-parent model should be immediately familiar to anyone
who's done basic web development.

Create a file ingredient.rb in app/models with the following contents:

If you chose SQLite3 as the relational database you wanted to use earlier, then
you don't need to change any database configuration. If you chose another
database, then open config/database.yml and change appropriately. For
PostgreSQL, or Microsoft SQL Server configurations might look like the
following:

Add a UI

Here I'm sorry to say we're going to cheat (yet again!). We're not actually
going to spend any time building a UI, but instead we'll rely on merb-admin, a
project that automatically generates an admin front-end similar to Django,
the Python web application framework.