Best way to create unique token in Rails?
Ryan Bates uses a nice little bit of code in his Railscast on beta invitations. This produces a 40 character alphanumeric string.
Digest::SHA1.hexdigest([Time.now, rand].join)
This might be a late response but in order to avoid using a loop you can also call the method recursively. It looks and feels slightly cleaner to me.
class ModelName < ActiveRecord::Base
before_create :generate_token
protected
def generate_token
self.token = SecureRandom.urlsafe_base64
generate_token if ModelName.exists?(token: self.token)
end
end
-- Update --
As of January 9th, 2015. the solution is now implemented in Rails 5 ActiveRecord's secure token implementation.
-- Rails 4 & 3 --
Just for future reference, creating safe random token and ensuring it's uniqueness for the model (when using Ruby 1.9 and ActiveRecord):
class ModelName < ActiveRecord::Base
before_create :generate_token
protected
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless ModelName.exists?(token: random_token)
end
end
end
Edit:
@kain suggested, and I agreed, to replace begin...end..while
with loop do...break unless...end
in this answer because previous implementation might get removed in the future.
Edit 2:
With Rails 4 and concerns, I would recommend moving this to concern.
# app/models/model_name.rb
class ModelName < ActiveRecord::Base
include Tokenable
end
# app/models/concerns/tokenable.rb
module Tokenable
extend ActiveSupport::Concern
included do
before_create :generate_token
end
protected
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless self.class.exists?(token: random_token)
end
end
end