Sam Saffron
Sam Saffron

Reputation: 131112

Generating GUIDs in Ruby

I have a problem that is really easily solved with GUIDs.

In particular, for a password reset workflow, I would like to send a GUID token to a user's email and have them reset their password using the token. Since GUIDs are unique, this is pretty secure and saves me emailing people passwords, which is risky.

I noticed there is one uuid gem @ rubyforge but it looks quite old, and it writes stuff to the file system.

Does anyone know of any other gems that can create a globally unique identifier?

I know I can just fall back to:

(0..16).to_a.map{ |a| rand(16).to_s(16) }.join 

But it does not really seem like a proper GUID ...

Upvotes: 172

Views: 111492

Answers (11)

robotmay
robotmay

Reputation: 1316

While programming late at night I came up with the following solution (based off Simone's answer) for generating a unique GUID in Rails. I am not proud of it but it does work quite well.

while Order.find_by_guid(guid = rand(36**8).to_s(36).upcase).present?; end

Upvotes: 1

Small update to Simone Carletti answer:

SecureRandom.base64(8).gsub("/","_").gsub(/=+$/,"")

=> "AEWQyovNFo0" 

can be replaced with:

SecureRandom.urlsafe_base64(8)

Upvotes: 6

Marc W
Marc W

Reputation: 19241

Google yields the following Ruby library.

Also, over at ruby-forum they say you can install a gem (execute gem uuid on the command line to install it) and then do

gem 'uuid'
puts UUID.new

in your code to see a new UUID.

(Hint: I Googled for guid ruby)

Upvotes: 16

Tilo
Tilo

Reputation: 33732

FOR NEW RAILS VERSIONS >= 5.1

For new Rails versions, you can now use the methods under Digest::UUID, e.g. Digest::UUID.uuid_v4

See API Docs:

Upvotes: 1

stevec
stevec

Reputation: 52248

For rails running a postgreSQL database do 2 things.

Step 1: generate a scaffold/model

rails g scaffold manager name:string --primary-key-type=uuid

Step 2: Add a line to migration file

If you rails db:migrate now, you'll get a PG::UndefinedFunction: ERROR: function gen_random_uuid() does not exist error.

So add this to the migration file

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

Example:

class CreateManagers < ActiveRecord::Migration[7.0]

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

  def change
    create_table :managers, id: :uuid do |t|
      t.string :name
      t.timestamps
    end
  end
end

You're done!

Oh one last thing, you only nee to add enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto') to one migration file (e.g. the first time you use uuid type).

Upvotes: 1

Sancarn
Sancarn

Reputation: 2824

This is a neet technique I learnt from JavaScript:

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        "0123456789ABCDEF"[rand(16)]
    end
end

Although in a more 'ruby way' one could also do:

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        rand(16).to_s(16)
    end
end

Upvotes: 1

Simone Carletti
Simone Carletti

Reputation: 176372

How to create small, unique tokens in Ruby

>> require 'digest'
=> []
>> Digest::SHA1.hexdigest("some-random-string")[8..16]
=> "2ebe5597f"

>> SecureRandom.base64(8).gsub("/","_").gsub(/=+$/,"")
=> "AEWQyovNFo0" 

>> rand(36**8).to_s(36)
=> "uur0cj2h"

Upvotes: 41

BMW
BMW

Reputation: 45223

When I used uuid gems recommended in this question, no one can generate unique and random UUID. My answer is a work around, if we have gem later to satisfy the request, you'd better to use gem in Ruby.

I try most recommended uuid gems in this question, but no one make me satisfied, we need unique and random uuid. I directly run system command uuidgen in ruby, and I like the result, and share here.

puts `uuidgen`
8adea17d-b918-43e0-b82f-f81b3029f688
puts `uuidgen`
6a4adcce-8f64-41eb-bd7e-e65ee6d11231
puts `uuidgen`
51d5348b-8fc3-4c44-a6f7-9a8588d7f08a
puts `uuidgen`
332a0fa3-7b07-41e1-9fc8-ef804a377e4e

if compare with uuid gem, you will know the difference.

irb(main):003:0> uuid.generate
=> "40cdf890-ebf5-0132-2250-20c9d088be77"
irb(main):004:0> uuid.generate
=> "4161ac40-ebf5-0132-2250-20c9d088be77"

Test environment is linux and Mac OS environment.

Upvotes: 0

J _
J _

Reputation: 4155

As of Ruby 1.9, uuid generation is built-in. Use the SecureRandom.uuid function.

For example:

require 'securerandom'
SecureRandom.uuid # => "96b0a57c-d9ae-453f-b56f-3b154eb10cda"

Upvotes: 364

Aaron Henderson
Aaron Henderson

Reputation: 1880

To create a proper, mysql, varchar 32 GUID

SecureRandom.uuid.gsub('-','').upcase

Upvotes: 5

Andrew Hare
Andrew Hare

Reputation: 351476

Did you look at UUIDTools?

UUIDTools was designed to be a simple library for generating any of the various types of UUIDs (or GUIDs if you prefer to call them that). It conforms to RFC 4122 whenever possible.

Upvotes: 22

Related Questions