Intro & Setup

Rails 4 has native support for UUID in PostgreSQL so I decided to give it a try in my test project.

First, you need to enable PostgreSQL extension ‘uuid-ossp’. Create a new migration like this:

rails generate migration enable_uuid_ossp

And edit the newly created migration file

class EnableUuidOssp < ActiveRecord::Migration
def change
enable_extension 'uuid-ossp'
end
end

After that, run rake db:migrate. After this, you can use start using :uuid as your table’s primary key in other migrations. For example:

rails generate migration create_users
class CreateUsers < ActiveRecord::Migration
def change
create_table :users, id: :uuid do |t|
t.string :username
t.string :fullname
t.string :email
t.string :encrypted_password
t.timestamps
end
end
end

You can also use :uuid not as ID replacement but on a specific column

class AddSuperIdToStudents < ActiveRecord::Migration
def change
add_column :students, :super_id, :uuid
end
end

Drawbacks

Using UUID as ID replacement will make Model.first and Model.last methods not working anymore (UUID is all about randomness after all). Luckily, you can use created_at attribute and implement default_scope in your model as following:

class User < ActiveRecord::Base
default_scope -> { order('created_at ASC') }
end

Or you can define you own scopes using created_at:

class User < ActiveRecord::Base
scope :first, -> { order("created_at").first }
scope :last, -> { order("created_at DESC").first }
end

Another problem is that t.references method in your migrations. If your users table have UUID as ID and you define reference to it in other tables using t.references :user, it will create a user_id column with integer as the type in those tables. Of course, it’s not going to work. You must specifically define the reference like this:

...
t.uuid :user_id
...