module Uniqueness module Model # :nodoc: def self.included(base) base.extend ClassMethods end module ClassMethods # Adds random field support to Rails models # # Examples: # To auto-generate a new random string for field +foo+ # has_random_field :foo # # You can customize the generated string by # passing an options hash. The following keys are supported: # # +:length+ number of characters, defaults to 32 # # +:case_sensitive+ defaults to true # # +:type+ type of string, defaults to :hash # can be one of: :human, :hash # # +:blacklist+ characters to exclude when generating the random string, # defaults to [] def has_unique_field(name, options = {}) validates name, presence: true, uniqueness: true before_validation do value = self.send(name) self.send("#{name}=", uniqueness_generate(options)) unless value end end end # Generates a new code based on given options def uniqueness_generate(opts = {}) options = { length: 32, type: :auto, blacklist: [] } options.merge!(opts) dict = uniqueness_dictionary - options[:blacklist] dict = dict - [*(:A..:Z)].map(&:to_s) unless options[:case_sensitive] dict = dict - uniqueness_ambigious_dictionary if options[:type].to_sym == :human Array.new(options[:length]).map { dict[rand(dict.length)] }.join end # Dictionary used for uniqueness generation def uniqueness_dictionary [*(:A..:Z), *(:a..:z), *(0..9)].map(&:to_s) end def uniqueness_ambigious_dictionary [1, 5, 8, :B, :o, :O, :I, :l, :L, :s, :S, :u, :U].map(&:to_s) end end end