module RandomUniqueId
Copyright © 2013, 2014, 2015, Watu
Constants
- VERSION
Public Class Methods
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
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 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 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
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
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