I need to generate uuid for my rails application. What are the options(gems) I have?
There are plenty of options, I recommend not to add additional dependencies and use SecureRandom
which is builtin:
SecureRandom.uuid #=> "1ca71cd6-08c4-4855-9381-2f41aeffe59c"
See other possible formats here.
Generating GUIDs in Ruby
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"
Generating a short UUID string using uuidtools In Rails
You don't need uuidtools for this. You can use Secure Random for this.
[1] pry(main)> require "securerandom"
=> true
[2] pry(main)> SecureRandom.hex(20)
=> "82db4d707c4c5db3ebfc349da09c991b7ca0faa1"
[3] pry(main)> SecureRandom.base64(20)
=> "CECjUqNvPBaq0o4OuPy8RvsEoCY="
Passing 4
and 5
to hex
will generate 8 and 10 character hex strings respectively.
[5] pry(main)> SecureRandom.hex(4)
=> "a937ec91"
[6] pry(main)> SecureRandom.hex(5)
=> "98605bb20a"
Ruby UUID and uniqueness, for an ID
No way. UUID is considered unique because it is very long and it is practically impossible to generate same UUIDs. If you trim it to 6 chars then you drammatically increase possiblility of duplicate. You have to use either incrementing id or full UUID.
Only deterministic generation (id(x + 1) = id(x) + 1
) can guarantee uniqueness. UUID doesn't guarantee it and 6 chars guarantee it even less.
Other option is to create ID generation service, it will have single method getNewId
and will keep knowledge that will be enought to provide unique ids. (Simplest case - counter)
Ruby on Rails 4.2 with Globalize gem for UUID table
I was not able to use the hardcoded solution provided by Thomas Engelbrecht because not all my models use uuid.
Since the model is delegated we can check it's primary key type by adding a method :
def primary_key_type
column_type(model.primary_key).to_sym
end
And i'm using Rails 4.2 so I can use the references type option ( source )
module Globalize
module ActiveRecord
module Migration
class Migrator
def primary_key_type
column_type(model.primary_key).to_sym
end
def create_translation_table
connection.create_table(translations_table_name, id: primary_key_type) do |t|
t.references table_name.sub(/^#{table_name_prefix}/, '').singularize, null: false, type: primary_key_type
t.string :locale, null: false
t.timestamps null: false
end
end
end
end
end
end
There must be a cleaner way, but I lack the experience to create a pull request.
UUIDs in Rails3
Are you declaring another before_create method in your Image model? If so, you'll be overriding the one in the UUIDHelper module. You'll want to either declare the callback a different manner, or call super in the callback in your image model.
Edit: Maybe change the helper to look something like this:
module UUIDHelper
def self.included(base)
base.class_eval do
before_create :set_uuid
def set_uuid
self.uuid = UUID.timestamp_create.to_s
end
end
end
end
Generate valid, deterministic UUIDs for tests
UUIDs use two digits to denote their format: (actually just some of the digit's bits)
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
^ ^
version variant
The following pattern denotes version 4 (M=4), variant 1 (N=8) which simply means "random bytes":
xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx
You could use it as a template to generate fake (but valid) UUIDs based on a sequence number: (as suggested in the comments)
def fake_uuid(n)
'00000000-0000-4000-8000-%012x' % n
end
fake_uuid(1) #=> "00000000-0000-4000-8000-000000000001"
fake_uuid(2) #=> "00000000-0000-4000-8000-000000000002"
fake_uuid(3) #=> "00000000-0000-4000-8000-000000000003"
Having it somewhat readable is a big pro ...
There are plenty of unused fields / digits to add more data:
def fake_uuid(klass, n)
k = { Company => 1, Employee => 2 }.fetch(klass, 0)
'%08x-0000-4000-8000-%012x' % [k, n]
end
fake_uuid(Company, 1) #=> "00000001-0000-4000-8000-000000000001"
fake_uuid(Company, 2) #=> "00000001-0000-4000-8000-000000000002"
fake_uuid(Employee, 1) #=> "00000002-0000-4000-8000-000000000001"
fake_uuid(Employee, 2) #=> "00000002-0000-4000-8000-000000000002"
# ^^^^^^^^ ^^^^^^^^^^^^
# class sequence
RoR roles management - rolify gem - use with resources of both UUID and Integer IDs
Well, you should just add a migrations to the database tables that you want to use UUID on. rails g migration add_uuid_to_sometablename
, and should be sufficient.
And if you need to index that particular column, you can say like
add_index(:yourtablename, :uuid, unique: true)
Related Topics
Ruby: Explicit Scoping on a Class Definition
Ubuntu 12 - How to Install Ruby and Rails Correctly
Rails: I Can't Call a Function in a Module in /Lib - What am I Doing Wrong
Ruby: What Does the Asterisk in "P *1..10" Mean
How to Solve the Update Bundler Warning in Rails When Deploying to Heroku
Testing Whether String Starts with or End with Another String
Group_By in Rails by 2 or More Attributes
Mapping Values from Two Array in Ruby
How to Validate Associated Model Id
What Are the Main Differences Between Sinatra and Ramaze
Building a Hash in a Conditional Way
Comparing Times Only, Without Dates
Calling/Applying Lambda VS. Function Call - the Syntax in Ruby Is Different. Why
Most Concise Way to Test String Equality (Not Object Equality) for Ruby Strings or Symbols
Carrierwave: Create the Same, Unique Filename for All Versioned Files