Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@rmoriz
Last active February 7, 2020 12:30
Show Gist options
  • Star 54 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save rmoriz/937739 to your computer and use it in GitHub Desktop.
Save rmoriz/937739 to your computer and use it in GitHub Desktop.
UUID primary keys in Rails 3
# Gemfile
gem 'uuidtools'
# db/migrate/20110422210841_create_sites.rb
# 1. :id => false
# 2. :uuid
#
class CreateSites < ActiveRecord::Migration
def self.up
create_table(:sites, :id => false) do |t|
t.string :uuid, :limit => 36, :primary => true
t.timestamps
end
end
def self.down
drop_table :sites
end
end
# app/models/site.rb
class Site < ActiveRecord::Base
include Extensions::UUID
end
# app/models/extensions/uuid.rb
#
module Extensions
module UUID
extend ActiveSupport::Concern
included do
# old rails versions
set_primary_key 'uuid'
# later rails versions, untested:
# self.primary_key = 'the_name'
before_create :generate_uuid
def generate_uuid
self.id = UUIDTools::UUID.random_create.to_s
end
end
end
end
Copy link

ghost commented Jul 16, 2011

My understanding is that the "set_primary_key 'uuid'" overrides the default behaviour of rails to use the uuid column instead of the id column. Nothing should break in the process.

@fionaom
Copy link

fionaom commented Jul 16, 2011

That did not work for me.

My test DB was still loaded with ID column with INT(11).

I'm on Rails 2.3.4.

@sethcall
Copy link

sethcall commented Aug 6, 2012

In Postgresql, you can have the database default null columns to a valid UUID, meaning you could do without any customization of rails beyond just writing a raw migration:

CREATE EXTENSION "uuid-ossp";

CREATE TABLE users (
    id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4()
);

@rmoriz
Copy link
Author

rmoriz commented Sep 6, 2012

If you're on postgres you want to look at https://github.com/dockyard/postgres_ext anyways :-)

@alex-ross
Copy link

Got this when i did run some spec:
DEPRECATION WARNING: Calling set_primary_key is deprecated. Please use self.primary_key = 'the_name' instead.

Haven't looked it up but i guess it's true. So please update folks ;)

@warmwaffles
Copy link

This isn't the best idea to let rails handle the UUID's. Race conditions are possible and collisions are possible. It's probably best to let MySQL or Postgres handle it via the built in function UUID(). I'm going to do a write up about it soon and how to accomplish UUID's with rails.

@gorn
Copy link

gorn commented Feb 5, 2013

I was using this approach for a long time, but now after upgrading it stops working. I also get

Got this when i did run some spec:
DEPRECATION WARNING: Calling set_primary_key is deprecated. Please use self.primary_key = 'the_name' instead.

and morover i get new error

uninitialized constant RSpec::Matchers::Extensions::UUID

in rspec tests when trying to use routing paths, which used to work.

Is there a update to this approach? (hopefully not radically different]

@rmoriz
Copy link
Author

rmoriz commented Apr 4, 2013

@warmwaffles you should probably read more about UUIDs and primary key uniqueness ;-)

When possible and you don't mind the database lock-in, do it in the database.

Sometimes, when you have an async API that pushes customer data e.g. on a MQ/redis. You need to generate and return the UUID on the customer-facing system. You can't wait/block for the full, async database round-trip.

@natebird
Copy link

If you are using Ruby 1.9.3+ you can just call SecureRandom.uuid. You also don't need gem 'uuidtools'.

Thanks for this.

@SandNerd
Copy link

For Rails 3.1+ check ActiveUUID

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment