Using UUIDs in ActiveRecord with PostgreSQL

Lightning talk #parisrb by @DorianLupu

February 2nd, 2016

What are UUIDs ?

Universally Unique IDentifier

 

32 lowercase hesadeximal digits

de305d54-75b4-431b-adb2-eb6b9e546014

 

Several variants/versions. V4 uses pseudo random numbers

 

Unique means "very likely to be unique"  ( 10^38 combinations)

When use UUIDs ?

 

when we need to uniquely identify objects without significant central coordination (distributed systems)

 

when we need to prevent information leaking (database enumeration)

 

Drawbacks

 

 a little bit slower to generate

 

require bigger indexes  

Using UUIDs with Active Record and PostrgreSQL

### db/migrate/20150418012400_create_blog.rb

# enable extension `pgcrypto` (only PostgreSQL >= 9.4) before using :uuid column type
# for older PostgreSQL versions use extension `uuid-ossp`
enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')

create_table :posts, id: :uuid
 
create_table :comments, id: :uuid do |t|
  t.references :post, type: :uuid
end
 
### app/models/post.rb
class Post < ApplicationRecord
  has_many :comments
  default_scope -> { order('created_at ASC') } # required      
end
 
### app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :post
  default_scope -> { order('created_at ASC') } # required     
end

Using UUIDs with Active Record and PostrgreSQL

### config/routes.rb
# optional : configure router to accept only UUIDs 

UUID_REGEXP = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i

Rails.application.routes.draw do
  resources :posts, constraints: { id: UUID_REGEXP } do
    resources :comments, constraints: { id: UUID_REGEXP }
  end
end

Using UUIDs with Active Record and PostrgreSQL

### config/application.rb
# optional : configure generators to always user :uuid as primary keys 


config.generators do |g|
  
  # use :uuid type for primary keys.
  g.orm :active_record, primary_key_type: :uuid

end

Migrating existing projects

### Gemfile
gem 'webdack-uuid_migration'  # works with Rails 4.x and 5.0

### db/migrate/20160202191500_uuid_migration.rb
require 'webdack/uuid_migration/helpers'

enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')

class UuidMigration < ActiveRecord::Migration
  def change
    reversible do |dir|
      dir.up do
        primary_key_to_uuid :posts     
        primary_key_to_uuid :comments
        columns_to_uuid :comments, :post_id
      end

      dir.down do
        raise ActiveRecord::IrreversibleMigration
      end
    end
  end
end

# existing IDs will be converted to UUID by appending leading zeros
# 123 will be converted to 00000000-0000-0000-0000-000000000123
# new IDs will be generated randomly 

Questions?

Using UUID in ActiveRecord with PostgreSQL

By Dorian Lupu

Using UUID in ActiveRecord with PostgreSQL

  • 1,122

More from Dorian Lupu