I have been hacking away at the latest of my mini-projects, a small program to catalogue my ever growing dead tree collection (in Ruby ofcourse, I don’t seem to code in anything else these days).
While the whole project is a learning exercise mostly in the use of web services, GUI building with FXRuby and a chance to use my purple barcode scanner (!!), I needed to find a non-cumbersome way to store the data.
While I had the whole object structure nicely thought out (on two pieces of napkin, but nevertheless in beautifully crude UML) I had no intention to burden myself with a database and tables and such. I needed something that would move with the program. You can’t expect to have a 600K executable and require that MySQL be installed just to view a collection of books (although for some wierd reason I do expect Ruby to be installed).
As it so happens, sometime ago, while still swimming in the seas of Java, I found Prevlayer, the “free software Prevalence layer for Java”. Succinctly put (and when dealing with Prevlayer you need to be brief or you’ll exceed in words the lines of code that whole thing has) it’s a transparent persistency method which keeps all objects in memory and periodically takes snapshots and serialises them on disk.
Now, I liked Prevlayer from the beginning. It’s fst (so fast you can’t pronounce the a), it’s simple (minimal code), it’s elegant (no more O-R mappings), it’s logical (no more O-R mappings), it’s beautiful (no more O-R mappings). Can you tell I like it?
Just as luck has it, Anders Bengtsson was generous enough to let us have a Ruby implementation of Prevalence, Madeleine.
First reaction: This can’t be. There is something I am missing here. Surely there is more to it than this!
Usage:
require 'madeleine'
madeleine = SnapshotMadeleine.new("my_example_storage") {
SomeExampleApplication.new()
}
madeleine.execute_command(command)
Close the browser, code some collections and data objects and come back to the above code afterwards. I did and I still can’t believe it.
Let’s see it up close:
I have a Book class with all the usual attributes (title, author, publisher etc.), two modules to mixin loan information (when and to whom) and owner details (comment, date read, time read etc.) and I tie everything together in a Bookcase class, which is essentially a collection of Books (much as the Songlist in Pickaxe 2nd Ed.) with added loan management. I know I should have called the class Library, and there was a Library with many Bookcases in the initial cave/napkin drawing, but with Ruby I tend to discard a lot of stuff when I reach the actual code level.
In memory it’s a very neat structure, easily usable in code, simple. At this stage I would normally have to spoil the picture to be able to save everything; Madeleine to the rescue:
require 'madeleine'
madeleine = SnapshotMadeleine.new("rivas_books") {Bookcase.new("Barcelona")}
the above two lines are 50% of the persistency layer for my application. The other 50% consists of the four command classes for adding, removing, loaning and returning a book (anything that changes the content of the Bookcase) and the following line when exiting the application:
madeleine.take_snapshot
Well, if you can prototype faster I would like to see it. It took me more time to write the article than to code the thing and I have everything I wished for with 20 lines of code! Can you tell I love it?