Postgres UUID in Rails
2014/03/17
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
...