DataMapper

DataMapper is an Object Relational Mapper written in Ruby. The goal is to create an ORM which is fast, thread-safe and feature rich.

Why you should use DataMapper

Speed

DataMapper combines tried and true principles from Martin Fowler’s design patterns with a pure ruby implementation, creating not only beautiful syntax, but a huge speed up from other popular ORMs.

Where other ORMs have failed you before, DataMapper strives to make up for this gap.

If this has piqued your interest, look below and learn how to get started.

If you’re looking for cold hard numbers, take a gander at the PERFORMANCE file. You’ll find the latest performance stats under “Current Performance”.

Most tests are run on a 2.16Ghz Core2Duo iMac.
Asterisk (*) indicates test run on 2.0Ghz Core2Duo MacBook.

Open Development

Found a bug or want a feature? Tired of dealing with the bureaucracy that other ORM maintainers force upon you?

The community surrounding DataMapper is open and friendly. Contributions of any kind are welcome, and the founder and maintainer of the project can be easily reached by using the fairly active mailing list (groups.google.com/group/datamapper) or by jumping in to the datamapper channel on irc.freenode.net.

Thread-Safe

Thread safety is a critical topic in any production software, and especially so with the DataMapper. The maintainers have dedicated much of their time to ensuring that the DataMapper is thread safe thus far, and will continue to do as much to ensure it stays that way.

Hacker Friendly

One of the most frustrating problems with other ORMs is the painstaking time it takes to understand and traverse the code-base.

DataMapper aims to be as lightweight as possible, keeping the code-base clean and uncluttered. Never be afraid to crack open the subversion trunk again!

Getting Started

Install DataMapper

There are two simple options for getting started with DataMapper.

If you’d like to use SVN and check out the bleeding edge version of the project, execute the following command in your terminal:

svn co http://datamapper.rubyforge.org/svn/trunk/ data_mapper

After checking out the trunk, point your application to the trunk/lib folder and require it.

If you’d like to just use datamapper and don’t plan on looking at the source code or want bleeding edge features, execute this instead:

gem install datamapper

QuickStart

If you want to find out how to use DataMapper in your existing application, jump to “Require it in your application”.

If you’d like to get started right away and play with the syntax of DataMapper, and you’re using MySQL as your database, create a new database called:

data_mapper_1

Then drop into the trunk directory, and execute:

rake

That will setup your database. From there, execute:

ruby example.rb

This will drop you into an IRB session, where you can further play with the syntax. Try out the intuitive finders:

Animal[0]
Animal.all
Zoo.first(:name => 'Galveston')
Zoo.find(:first, :conditions => ['name = ?', 'Galveston'])

Require it in your application

require 'rubygems'
require 'data_mapper'

Specify a Database Connection

Datamapper has Merb and Rails users in mind when setting up. If you’ve already setup a Merb or Ruby on Rails project, and have a database.yml, DataMapper should pick it up automatically.

If you’d like to set the database connection manually before using it, do something like this:

DataMapper::Database.setup({
  :adapter  => 'mysql',
  :host     => 'localhost',
  :username => 'root',
  :password => 'R00tPaswooooord',
  :database => 'selecta_development'
})

The currently supported databases are:

PostgreSQL

(postgresql adaptor)

MySQL

(mysql adaptor)

SQLite3

(sqlite3 adaptor)

Define Your Models

Defining your models requires a few steps.

  • Include the module DataMapper::Persistence in your class

  • Define your properties you wish to access from the database

  • Define any relationships (optional)

Unlike many other ORMs, DataMapper requires that you define which fields in the database you’d like to make available to your models as properties. There are a few reasons for this, which are too numerous to go into here.

Your models might end up looking something like this:

class Animal
  include DataMapper::Persistence

  property :name, :string
  property :notes, :text, :lazy => true

  has_one :favourite_fruit, :class => 'Fruit', :foreign_key => 'devourer_id'
  has_and_belongs_to_many :exhibits
end

Lazy Attributes

Lazy attributes are one of the many speed enhancing features in DataMapper.

Properties that are given the lazy attribute will not be loaded until they are accessed by your code.

So if you were to load a set of database records from your database, and only used the lazy property of those records occasionally, your memory signature will essentially stay much smaller, while still easily allowing you to gain access to those attributes when you need them.

For example, if you were to load all of the Animals using the class above, and were to inspect the set of returned data, you’d notice that all of the notes fields were nil. If you were to do something like the following:

animals = Animals.all
animals.inspect

You’d notice the nil fields immediately.

If you were to do something like the following:

animals.first.notes
animals.inspect

You’d notice that ALL of the notes fields in your set were loaded into memory.

The astute rubyist will immediately wonder if this is possible on associations, and indeed it is! This inevitably avoids the 1+N query problems that have so plagued us in the past. It allows us to develop in an intuitive manner, so that if we executed a loop:

animals.each do |animal|
  #The next line crafts a query to fetch ALL of this
  #set's favorite_fruit attributes
  puts animal.favorite_fruit
end

Only two queries hit our database. All with the automagical power of DataMapper!

Associations

DataMapper’s associations are exactly like the other ORMs out there. Some association examples are found below:

  • belongs_to :model

  • has_one :model

  • has_many :model

  • has_and_belongs_to_many :model

You can also set the class and foreign_keys for each association if you need to override the default naming scheme.

AutoMigrations

With DataMapper, there’s no need to constantly create migration after monotonous migration during your initial development.

Once you’ve got your models to a point where you’d like a table associated with them, simply execute the following:

database.save(ModelName)

This will generate the table structure for your model automatically.

You can also execute the following to generate ALL of your models’ tables:

DataMapper::Persistence.auto_migrate!

NOTE

Both of these methods are DESTRUCTIVE. If you are working in anything other than a pre-production environment, stay far away from these methods!

Conventions

Merb’s coding conventions are a fantastic start: (merb.devjavu.com/#ContributingtoMerb)

DataMapper could use some documentation help. If you’d like to contribute, the example you’ll find on the above link is top-notch.