UPDATED 2007-11-24
I had a few minutes this afternoon to update the article to the latest edge versions of Merb and DataMapper. Leave a comment if you’re having problems.
Last week I gave a presentation at New Bamboo on Merb and DataMapper. Keep an eye on the Bamboo blog, I’ll be posting my presentation about why you’d want to use DataMapper on there, minus the Borat jokes.
In my free time I’m working on an open source issue management application that uses Merb and DataMapper. Yes, I know both those projects are still very bleeding edge, but I’ve used Merb in production for nearly a year now. True, I’ve I had to peek at the innards of Merb when I had a few problems, but these days Merb is very stable and besides unlike Rails the code is very readable and well spec’ed. DataMapper feels a lot like Merb in that it too has a very nice code base that is easy to grok and has a decent set of specifications so contributing fixes and enhancements is going to be a whole lot easier.
Anyways, it was during my presentation the other day that I realised that not a lot of people know how to get Merb and DataMapper working with each other. There’s no formal guide as far as I can see and it’s scatterred around various places such as trac tickets, mailing list posts and just reading the source of Merb and DataMapper.
So let’s get started! I always work from trunk for both DataMapper and Merb, so lets check them out:
svn co http://svn.devjavu.com/merb/trunk merb svn co svn://rubyforge.org/var/svn/datamapper/trunk datamapper
Now that we’ve checked those out we need to do some prep before we install them. So let’s install some gems.
sudo gem install mongrel json_pure erubis mime-types \
rspec hpricot mocha rubigen haml \
ruby2ruby mailfactory markaby -y
First on the agenda is to install Merb
cd merb sudo rake install
All done? OK, lets get our DataMapper on.
cd .. cd datamapper rake gem sudo gem install pkg/datamapper-0.2.3.gem
You should now have DataMapper installed, except it won’t work. In their constant strive for performance the authors of DataMapper have written their own DB drivers so you’ll need to install those next. I’ll be using the MySQL drivers, but if you want to contribute to DataMapper you’ll also need to install the sqlite3 drivers so that you can run the specs.
I’ve used macports to install my version of Ruby, so my gems are installed in /opt/local/lib/ruby/gems your gems however maybe installed somewhere else such as /usr/local/lib/ruby/gems so change the path below to your systems setup.
cd /opt/local/lib/ruby/gems/1.8/gems/datamapper-0.2.3 sudo rake dm:install:mysql
If you get a bucket full of warnings don’t worry, it’s to do with docs being built for the C extensions.
You should now have a fully functional install of DataMapper. Let’s setup Merb to use this lovely ORM. Merb is a very lightweight framework and so all the optional functionality has been abstracted to plugins, which includes the DataMapper plugins.
First, lets check out and install the DataMapper Merb plugin
svn co http://svn.devjavu.com/merb/plugins/merb_datamapper cd merb_datamapper rake gem sudo gem install pkg/merb_datamapper-0.4.4.gem
Everything is now in place to start writing our Merb app. Create a new app by typing the following at the command line.
merb dm_app
You should have a new app skeleton in the dm_app directory. Load up the dependencies.rb file and make sure it looks similar to this:
# Make the app's "gems" directory a place where gems are loaded from Gem.clear_paths Gem.path.unshift(MERB_ROOT / "gems") # Make the app's "lib" directory a place where ruby files get "require"d from $LOAD_PATH.unshift(MERB_ROOT / "lib") use_orm :datamapper use_test :rspec ### Add your other dependencies here # These are some examples of how you might specify dependencies. # # dependencies "RedCloth", "merb_helpers" # OR # dependency "RedCloth", "> 3.0" # OR # dependencies "RedCloth" => "> 3.0", "ruby-aes-cext" => "= 1.0" Merb::Server.after_app_loads do ### Add dependencies here that must load after the application loads: # dependency "magic_admin" # this gem uses the app's model classes end
Add any other dependencies you want to this file. The last file you need to change is the database.yml, which should look very similar to an ActiveRecord database.yml file. The only difference is that I removed the socket configuration as DataMapper was throwing an error for me.
Update I forgot that the database.yml file isn’t automatically generated. If you don’t have one then you’ll need to create it in the config directory.
:development: &defaults :adapter: mysql :database: dm_app_development :username: root :password: :host: localhost :test: <<: *defaults :database: dm_app_test :production: <<: *defaults :database: dm_app_production
Start up your favourite mysql client such as YourSQL, or in my case the command line client and create the databases that you specified in the database.yml. All done? Good, let’s create our first model.
When you enable the Merb DataMapper plugin in the dependencies.rb file you’ll instantly get a few extra rake tasks and a few alternative options for the generate command found in the script directory. One of this is the dm_model option.
script/generate dm_model noodle
This command should of created a class called Noodle in the models directory together with a spec skeleton. Unlike AR, DataMapper attributes are specified in the model. Some people like this, others hate it. Personally I prefer it. If you’ve ever had the chance to use Og the following will all look very familiar to you.
class Noodle < DataMapper::Base property :name, :string property :description, :text validates_length_of :name validates_presence_of :description end
You specify your attributes and their types with the property method. Easy enough. You’ve probably also noticed that I’ve added some validations to the model and that they look exactly like AR validations. Well you’re right. DataMapper tries to make it as easy as possible for AR users to migrate to DataMapper. There are a few things that are different from AR or just behave in a different fashion to AR methods, but these should all be easy to get to grips with, especially if you’re like me and have a good RSpec suite for your code.
Something else you might have noticed is that I didn’t specify an ID property in my model. DataMapper assumes you want this automatically and adds it behind the scenes. You can override this if you want by adding your own property called ID, but I wouldn’t recommend it. At least not while you’re getting started.
This paradigm also continues for foreign keys. If you specify a relationship such as belongs_to etc, DataMapper will take care of the ID properties in the background.
OK, we’ve got our model setup but we can’t do anything with it yet as there still needs to be a definition of all the models properties in the database. If you do a rake—tasks in the root of the app you’ll probably notice that you’ve got a task called rake dm:db:migrate. Now I don’t actually use migrations when developing with DataMapper, this is because migrations currently don’t work, at least I couldn’t get them to work. However DataMapper has a really cool feature called auto migrations! What is this you say? Well if you load up the Merb irb console like so:
merb -i
Or if you want to do this in test mode
merb -i -e test
And then type the following in
DataMapper::Base.auto_migrate!
Update I was looking through svn and noticed that there’s now a nice rake task that comes with the DataMapper merb helper that performs the auto migration for you. Simply run:
rake dm:db:automigrate
You’ll now see that DataMapper has created a noodles table and populated it with the required columns. Beware that brave mariners and database data have known to go missing with this command as it be destructive, arrr.
So there you have it, a functional Merb environment in which you can start developing your next generation web application using DataMapper. Have fun mates!