With DataMapper, it can be quite a challenge to perform tasks that seem so simple at first. DataMapper is an object-relational mapper (ORM) written in Ruby, with a lot of great features and innovative approaches to common ORM-tasks. But it lacks documentation for some of the less-used features and even the more popular search engines don’t have the answer to all questions.
Note: the following examples have been tested with DataMapper version 0.10.2.
One of the questions I had was how to perform multiple queries within a single (database) transaction, so that I can ’stage’ a number of database queries and commit (or rollback) them all in one go. Fortunately, after some investigation of the DataMapper source code, it turns out to be an extremely simple task:
User.transaction do User.first.update(:name => "John Smith") Address.first.update(:street => "") # Invalid: street must not be blank end
With this code neither the address nor the user will be updated in the database if one of the updates fails. The syntax is actually the same as for the ActiveRecord ORM. However, triggering a rollback is done differently, as can be seen in the following example.
User.transaction do |t| User.first.update(:name => "John Smith") Address.first.update(:street => "Oak St. 400") t.rollback # Transaction will be rolled back even when updates are OK. end
That’s it for now. I’m sure there are some additional features that I haven’t mentioned here, but this is all I had to know at this point.
Running cucumber features with sunspot_rails
We wanted to integrate the sunspot_rails gem into our cucumber features. I found a ticket where mat adviced to call Sunspot::Rails::Server.start / stop in one of the available cucumber hooks.
Code found in features/support/env.rb is run when Cucumber begins and exits so this seemed the right place to start Solr:
Also, make sure you’ve added a cucumber environment to the config/sunspot.yml file; we copied the test-environment for that:
Running cucumber will let all scenarios fail unfortunately and we got a ‘Connection refused – connect(2) (RSolr::RequestError)‘ in our console.
The reason for this is simple (after I stepped into the sunspot_rails gem to be honest): the Sunspot::Rails::Server.new.start method will eventually launch a Java Servlet Container (Jetty) with the Solr WAR and uses the port defined in your sunspot.yml.
Now, starting up a server could take some time, so if cucumber’s features are run before the Solr server is up and running, the ‘Connection refused’ sounds trivial then.
First I added a sleep after starting up the server:
and this will work for most cases, but I thought it would be better to let cucumber wait just long enough until the server is up and running. When the server is up, you can open up your browser and enter http://localhost:8981/solr to administering Solr. This we can use to find out if we’ve waited long enough and start our features. I’ve put this into a seperate class named CukeSunspot and created this file in the features/support directory:
Now we can the alternative start method and remove the explicit sleep statement in our global before hook. features/support/env.rb:
And voila, if you run cucumber, you scenario’s should run successfully. On my machine: