tulipemoutarde.be

Software Developer

Smalltalk, Obj-C, Javascript, Ruby

@fstephany | Email | LinkedIn

+32 65 70 91 31

I'm currently working at Ta Mère SCRL a small development shop in Belgium.

We mainly do mobile apps (iOS, Android) for clients. Our backends are built with Ruby On Rails or with Pharo Smalltalk.

logo Ta Mère SCRL

MongoDB with Voyage in Pharo

24 May 2012 in magritte mongoDB pharo smalltalk voyage 

Esteban published Voyage, a library for persisting objects in Smalltalk. It uses Magritte to get descriptions from your domain model. At the moment, MongoDB and the image are the two possible backend for Voyage.

If you are not familiar with MongoDB and Document based databases, this presentation (~1h) by Jared Rosoff should help you to grasp the differences with the RDBMS world.

I wanted to play a bit with Pharo and MongoDB, there’s a MongoTalk, a simple smalltalk driver which works well but is quite low level. I wanted something that can be easily integrated with Magritte.

Here’s some dabbling with it and Pharo 1.4 (version 14441). Nothing really fancy, we will just save an object.

The Metacello configuration will take care of installation:

Gofer it
  url: 'http://smalltalkhub.com/mc/estebanlm/Voyage/main';
  package: 'ConfigurationOfVoyage';
  load.

ConfigurationOfVoyage project bleedingEdge load: 'Mongo'.

Update August 2012 Esteban created two different configuration ConfigurationOfVoyageMongo and ConfigurationOfPierVoyage. You should use the former for loading Voyage:

Gofer it
  url: 'http://smalltalkhub.com/mc/estebanlm/Voyage/main';
  package: 'ConfigurationOfVoyageMongo';
  load.

(ConfigurationOfVoyageMongo project version: '1.0') load: 'Mongo'.

We are going to assume you have a default MongoDB setup.

repo := VOMongoRepository
  host: VOMongoRepository defaultHost
  database: 'voyage-play'.

And setup this repository as the default one:

VORepository setRepository: repo.

Declare a new class. Don’t pay attention to my model, I’m designing the next social network that will bring humans to Mars.

Object subclass: #Brolinou
  instanceVariableNames: 'title'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'Brol'

Brolinou>>title
  ^title

Brolinou>>title: aString
  title := aString

Brolinou class>>isPersistent
  ^true

The last one is important. Voyage is now aware that you can persist Brolinou objects.

The weird thing is that Voyage currently depends on Magritte 2. I don’t know if you’ve already migrated to Magritte 3 but it bothers me a bit to start a new project with Magritte 2. I’m by no means a Magritte expert, there a probably good reasons to stay with that version. It is maybe that time is scarce and that Esteban is working like crazy on many other projects ;)

Anyway we gonna add a description for our title field:

titleDescription
  ^MAStringDescription new
     label: 'titre';
     accessor: #title;
     yourself.

Time to open a workspace and dabble with our model:

brol := Brolinou new title: 'Going to Mars!'.
brol isNew. "=> true"
brol save.

Tadadada! Open the Mongo shell or your favorite interface to it (I’m using RockMongo). You should see a new collection. The weird thing is that the new collection is named olinou in the database voyage-play. I was expecting something like brolinou. Remember that we are running the bleeding edge version of Voyage so it’s not that important.

You should have an entry that looks like:

{
   "_id": ObjectId("69b4a62c0000000000000000"),
   "#instanceOf": "Brolinou",
   "title": "Going to Mars!"
}

We can see here that a field `#instanceOf" has been added to the record. It is probably used at materialization. You can now query your class to retrieve all the Brolinou instances:

Brolinou selectAll.
Brolinou selectMany: { #title -> 'Going to Mars!'} asDictionary.

To see all the available methods, browse the Voyage-Model-Core protocol in the class Class. The persistence protocol of VOMongoRepository is quite interesting as well.

That’s all! Here are the topics I’d like to cover next:

  • Queries
  • Index
  • So far, Voyage will create a collection named after the class. With embedded objects you don’t always want that behavior. There’s probably a way to override that, i’m wondering how it is made.

EDIT

The issue with the collection name is caused by the following code:

VOMongoContainer class>>defaultCollectionName
  ^(self label allButFirst: 2) asLegalSelector

This decision was probably made because of the lack of namespaces in Pharo. So people prefix their model class with two letters (e.g., WATag, FSLocator, ZnEntity). It makes sense now.

Edit two

It seems that the Magritte description is useless in this case. Voyage will happily serialize the title instance variable automatically. See my next post for more.