module RandomUniqueId

Copyright © 2013, 2014, 2015, Watu

Constants

VERSION

Public Class Methods

config(options={}) click to toggle source

The global configuration for RandomUniqueID. Set it in initializers

RandomUniqueId.config(field: :rid,
                      random_generation_method: :short,
                      min_rid_length: 5)

@param [Hash] options @option options [Symbol] field the name of the field where the random unique id is stored. @option options [Symbol] random_generation_method the method to generate random IDs, ‘:short` or `:uuid`.

`:short` will generate a short-ish random ID, and check that it is unique
`:uuid` will generate a UUID, and skip the check. This is better for performance, and bad for readability of IDs

@option options [FixNum] min_rid_length the minimum length RandomUniqueID will generate. Defaults to 5 @return [Hash] the configuration.

# File lib/random_unique_id.rb, line 28
def self.config(options={})
  @@config ||= {field: :rid, random_generation_method: :short, min_rid_length: 5}
  @@config = @@config.merge(options)
end
generate_short_random_id(length=10) click to toggle source

By a cunning use of SecureRandom.urlsafe_base64, quickly generate an alphanumeric random string.

@param length [Integer] how long should the random string be. @return [String] the random string. @see RandomUniqueId#populate_rid_field

# File lib/random_unique_id.rb, line 191
def self.generate_short_random_id(length=10)
  # IMPORTANT: don't ever generate dashes or underscores in the RIDs as they are likely to end up in the UI in Rails
  # and they'll be converted to something else by jquery ujs or something like that.
  generated_rid = ""
  while generated_rid.length < length
    generated_rid = (generated_rid + SecureRandom.urlsafe_base64(length * 3).downcase.gsub(/[^a-z0-9]/, ""))[0..(length-1)]
  end
  return generated_rid
end
generate_uuid() click to toggle source

Generate a UUID. Just a wrapper around SecureRandom.uuid @return [String] the new UUID. @see RandomUniqueId#populate_rid_field

# File lib/random_unique_id.rb, line 204
def self.generate_uuid
  SecureRandom.uuid
end

Public Instance Methods

generate_short_random_unique_id(length, field) click to toggle source

Generate random ids, increasing their size, until one is found that is not used for another record in the database. @param length [Integer] how long should the random string be. @param field [String] name of the field that contains the rid.

# File lib/random_unique_id.rb, line 162
def generate_short_random_unique_id(length, field)
  potential_unique_random_id = nil
  begin
    potential_unique_random_id = RandomUniqueId.generate_short_random_id(length)
    length += 1
  end while topmost_model_class.unscoped.where(field => potential_unique_random_id).exists?
  potential_unique_random_id
end
populate_rid_field(length=random_unique_id_options[:min_rid_length], field=random_unique_id_options[:field]) click to toggle source

Generate and store the random unique id for the object.

@param length [Integer] how long should the random string be. Only applicable for ‘:short` type. @param field [String] name of the field that contains the rid. @return [String] the random string. @see RandomUniqueId::ClassMethods#has_random_unique_id @see RandomUniqueId.generate_random_id

# File lib/random_unique_id.rb, line 148
def populate_rid_field(length=random_unique_id_options[:min_rid_length], field=random_unique_id_options[:field])
  case random_unique_id_options[:random_generation_method]
    when :short
      self.send("#{field}=", generate_short_random_unique_id(length, field))
    when :uuid
      self.send("#{field}=", RandomUniqueId.generate_uuid)
    else
      raise "Invalid random generation method: #{self.random_unique_id_options[:random_generation_method]}"
  end
end
topmost_model_class() click to toggle source

Find the topmost class before ActiveRecord::Base so that when we do queries, we don’t end up with type=Whatever in the where clause. @return [Class] the class object

# File lib/random_unique_id.rb, line 174
def topmost_model_class
  @topmost_model_class ||= begin
    klass = self.class
    self.class.ancestors.select { |k| k.is_a? Class }.each do |k|
      if k == ActiveRecord::Base
        return klass
      end
      klass = k
    end
  end
end