Introduction
Rails 5.1 brings many improvements and plenty of changes. Among them is the change of function that is used when generating UUIDs.
For PostgreSQL >= 9.4, ActiveRecord will now use pgcrypto
’s gen_random_uuid
function whereas previously uuid-ossp
’s uuid_generate_v4
function was used.
Follow these steps to add UUID primary keys to your Rails 5.1+ application.
Add a migration
First we need to enable the PostgreSQL pgcrypto
extension in a migration. Lets start by creating a blank migration:
$ rails generate migration enable_pgcrypto_extension
Then change the file to enable the extension. It should look something like this:
class EnablePgcryptoExtension < ActiveRecord::Migration[5.1]
def change
enable_extension 'pgcrypto'
end
end
Change the primary default type
When you generate models ActiveRecord will use Integer
as the type for id
by default. In Rails 5 you can change this behaviour by adding the following to your config/application.rb
file.
config.generators do |g|
g.orm :active_record, primary_key_type: :uuid
end
Try it out
Now when you run rails generate model post title:string
your migration file should look something like this:
class CreatePosts < ActiveRecord::Migration[5.1]
def change
create_table :posts, id: :uuid do |t|
t.string :title
t.timestamps
end
end
end
Further help
It’s most likely you’ve ended up here from a Google search, here are some errors that you might experience that relate to this guide:
I get an error about gen_random_uuid
when I run rake db:migrate
?
If you get the following error when you run rake db:migrate
then it’s likely you’ve hit the issue I wrote this post above.
function gen_random_uuid() does not exist
I get an error about uuid_generate_v4
when I run rake db:migrate
?
If you get the following error when you run rake db:migrate
:
function uuid_generate_v4() does not exist
It’s likely you have old references to uuid_generate_v4
in your code. Most likely a migration like this:
add_column :posts, :id, default: "uuid_generate_v4()", null: false
To ensure all your old as well as your new migrations continue to run simply enable both extensions in a migration:
class EnablePgcryptoExtension < ActiveRecord::Migration[5.1]
def change
enable_extension 'uuid-ossp'
enable_extension 'pgcrypto'
end
end