Category: datamapper

migrating to datamapper 0.9 - unique indexes

Posted by on June 9, 2008

This is a first post on migrating from datamapper 0.2.5 to 0.9. 0.9 is a complete rewrite of datamapper so careful attention needs to be applied for this migration. ShellShadow is in production with 0.2.5 and I hope to get a new release out on 0.9 very soon so I’ll be posting my experiences as I go.

The first thing I have encountered is a key difference in defining unique indexes.

In 0.2.5 ( or 0.3) you would write something like this:

class User < DataMapper::Base
property :email, String, :index => :unique
property :display_name, String, :index => :unique

which would produce SQL indexes (for postgres) as:

Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"users_display_name_key" UNIQUE, btree (display_name)
"users_email_key" UNIQUE, btree (email)
"users_display_name_index" btree (display_name)
"users_email_index" btree (email)

doing a fairly straightforward conversion to datamapper 0.9 yields the following:

class User
include DataMapper::Resource
property :id, Integer, :serial => true
property :email, String, :index => :unique
property :display_name, String, :index => :unique

which generate these SQL indexes (postgres):

Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"index_users_unique" btree (email, display_name)

This creates a single unique index on the combined fields email and display_name; not what I want. I assume this is quite possibly an intended effect as this is how combined key fields gets handled in the new dm 0.9. After a few minutes looking through the very clean datamapper 0.9 source, I find there a constraint type called unique_index. When I use this as follows:

class User
include DataMapper::Resource
property :id, Integer, :serial => true
property :email, String, :unique_index => true
property :display_name, String, :unique_index => true

I get indexes generated as:

Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"unique_index_users_display_name" UNIQUE, btree (display_name)
"unique_index_users_email" UNIQUE, btree (email)

much better!!!

monkeypatching merb

Posted by on April 7, 2008

If you never heard of merb, stop reading this and go check it out!!!

One of things you will encounter when using the coolest and latest technologies is that they might contain bugs ;). It is what we encountered in using datamapper 0.2.5 and do_postgres 0.2.3 in our merb 0.9.2 development stack for ShellShadow.

Here’s a quick look at how we add our patches into our merb app.

One of nasty bugs existing in datamapper 0.2.5 or 0.3.0 is that it will interpret NULL integer fields from a table as 0. It was a huge issue for us and had to be patched.

Turns out the culprit is not datamapper but in do_postgres. Many thanks to Adam French for pointing this out on #datamapper irc channel.

The buggy code was in [GEM_PATH]/gems/do_postgres-0.2.3/lib/do_postgres.rb in class Reader < DataObject::Reader method typecast(val, field_type).

The code in questions was:

when "INT2", "INT4", "OID", "TID", "XID", "CID", "INT8"
val.to_i

This should read:

when "INT2", "INT4", "OID", "TID", "XID", "CID", "INT8"
val == "" ? nil : val.to_i

The fix was a one liner but we needed to replace the entire method it was in.

This is how you apply your monkeypatch:

  1. Add your patch file under <your_merb_project>/lib. Lets call it do_postgres_patch.rb. We put our modified copy of typecast in this file.
  2. In <your_merb_project>/config/init.rb, you’ll see at the very bottom

  3. Merb::BootLoader.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

    In this block, add:
    require 'core_extensions'

That’s it. Easy and all patched up!!!