module RandomToken

Constants

ALPHABETS

The alphabet seed

DEFAULT_OPT

The default option definition

MASK

The default friendly mask

NUMBERS

The number seed

SEED_TYPES

The default seeds definition

STRF_ARG_MAP

The directives used in the format string

SUPPORTED_OPTS

The supported options

VERSION

Public Class Methods

gen(arg, options = {}) click to toggle source

The major method to generate a random token. @param arg [Fixnum, String]

To give a token length or the string format for generating token.

@param options [Hash]

The options to modify the token.
Three options :seed, :friendly and :case are supported.
Please see {file:README} to get more examples

@return [String]

The generated token.

@raise [RandomTokenError]

Please see {RandomToken::RandomTokenError}
# File lib/random_token.rb, line 118
def gen(arg, options = {})
  arg_dispatcher(arg, options) do |length, seeds|
    (0...length).map{ seeds[SecureRandom.random_number(seeds.length)] }.join
  end
end
genf(arg, options = {}) click to toggle source

A convenient method to generate a friendly token. It would call {RandomToken.gen} with :friendly => true option. @param arg (see RandomToken.gen) @param options (see RandomToken.gen) @return (see RandomToken.gen) @raise (see RandomToken.gen)

# File lib/random_token.rb, line 129
def genf(arg, options = {})
  gen(arg, { :friendly => true }.merge(options))
end
get(arg, options = {}) click to toggle source

An old method for downward compatibility and it should be discarded. Use “gen” instead. @param arg (see RandomToken.gen) @param options (see RandomToken.gen) @return (see RandomToken.gen) @raise (see RandomToken.gen)

# File lib/random_token.rb, line 153
def get(arg, options = {})
  gen(arg, options)
end
strf(arg, options = {}) click to toggle source

An old method for downward compatibility and it should be discarded. Use “gen” instead. @param arg (see RandomToken.gen) @param options (see RandomToken.gen) @return (see RandomToken.gen) @raise (see RandomToken.gen)

# File lib/random_token.rb, line 163
def strf(arg, options = {})
  gen(arg, options)
end

Private Class Methods

arg_dispatcher(arg, options, count = false) { |length, seeds| ... } click to toggle source

Decide how to generate/count token according to the arg type.

# File lib/random_token.rb, line 170
    def arg_dispatcher(arg, options, count = false)
      options = check_opt(options)
      unless block_given?
        raise RandomTokenError.new(
          "No block is given when calling arg_dispatcher.")
      end
      if arg.is_a?(Integer)
        run_by_length(arg, options) do |length, seeds|
          yield(length, seeds)
        end
      elsif arg.is_a?(String)
        result = run_by_pattern(arg, options) do |length, seeds|
          yield(length, seeds)
        end
        return result.join
        # TODO: Add count feature
=begin
        if count
          return result.delete_if { |x| x.is_a?(String) }.inject(0, :*)
        else
          return result.join
        end
=end
      else
        raise RandomTokenError.new(:invalid_gen_arg, arg)
      end
    end
check_opt(opts) click to toggle source

Check options

# File lib/random_token.rb, line 259
def check_opt(opts)
  SUPPORTED_OPTS.each do |key, value|
    if opts[key] && opts.keys.include?(value[:abbr])
      raise RandomTokenError.new(:duplicated_option, opts)
    end
    opts.merge!(key => opts[value[:abbr]]) if opts[value[:abbr]]
    if value[:value] && opts[key] && !value[:value].include?(opts[key])
      raise RandomTokenError.new(:invalid_option_value, opts)
    end
  end
  opts
end
gen_seeds(opt) click to toggle source

Generate seeds according to the :seed options

# File lib/random_token.rb, line 273
def gen_seeds(opt)
  opt_seed = opt[:seed]
  default_opt = SEED_TYPES[:default]
  if opt_seed == nil || opt_seed.is_a?(Symbol) || opt_seed.is_a?(Fixnum)
    SEED_TYPES.each do |key, value|
      if ([key] + value[:abbr]).include?(opt_seed)
        opt.delete(:seed)
        opt = default_opt.merge(value).merge(opt)
        opt[:seed] = opt[:seed].map { |s| s.to_a }.flatten
        return seed_modifier(opt)
      end
    end
    raise RandomTokenError.new(:unknown_seed, opt_seed)
  elsif opt_seed.is_a?(Array)
    return seed_modifier(default_opt.merge(:case => :keep).merge(opt))
  elsif opt_seed.is_a?(Hash)
    seeds = opt_seed.to_a.map {|s| (s.first * s.last).split(//)}.flatten
    return seed_modifier(default_opt.
                         merge(opt).
                         merge(:seed => seeds,
                               :support_case => false,
                               :support_friendly => false ))
  else
    raise RandomTokenError.new(:unknown_seed, opt_seed)
  end
end
run_by_length(length, options) { |length, seeds| ... } click to toggle source

Generate/count token with a given length.

# File lib/random_token.rb, line 199
def run_by_length(length, options)
  if block_given?
    final_opt = gen_seeds(options)
    seeds = final_opt[:seed]
    length = length * final_opt[:byte_mult] if final_opt[:byte]
    yield(length, seeds)
  else
    raise RandomTokenError.new(
      "No block is given when calling run_by_length.")
  end
end
run_by_pattern(pattern, options = {}) { |length == "" ? 1 : to_i, seeds| ... } click to toggle source

Generate/count token with a format string.

# File lib/random_token.rb, line 212
def run_by_pattern(pattern, options = {})
  unless block_given?
    raise RandomTokenError.new(
      "No block is given when calling run_by_pattern.")
  end
  if options[:byte]
    raise RandomTokenError.new(:format_not_support_byte, options)
  end
  in_arg = false
  result = []
  length = ''
  pattern.split(//).each do |x|
    if x == '%'
      if in_arg
        result << x * (length == "" ? 1 : length.to_i)
        length = ''
        in_arg = false
      else
        in_arg = true
      end
    elsif ('0'..'9').include?(x)
      if in_arg
        length << x
      else
        result << x
      end
    elsif STRF_ARG_MAP.keys.include?(x)
      if in_arg
        seeds = gen_seeds(STRF_ARG_MAP[x].merge(options))[:seed]
        result << yield((length == "") ? 1 : length.to_i, seeds)
        length = ''
        in_arg = false
      else
        result << x
      end
    else
      if in_arg
        raise RandomTokenError.new(:invalid_strf_pattern, pattern)
      else
        result << x
      end
    end
  end
  result
end
seed_modifier(opt) click to toggle source

Modify seeds according to the :case, :friendly and :mask options

# File lib/random_token.rb, line 301
def seed_modifier(opt)
  if opt[:support_case]
    case_opt = opt[:case] || opt[:default_case]
    case case_opt
      when :up, :u
        cased_seed = opt[:seed].map { |s| s.upcase }
      when :down, :d, :lower, :l
        cased_seed = opt[:seed].map { |s| s.downcase }
      when :mixed, :m
        cased_seed = opt[:seed].map { |s| [s.upcase, s.downcase] }.flatten
      else
        # :keep, keep the seed case
        cased_seed = opt[:seed]
    end
    opt[:seed] = cased_seed.uniq
  else
    raise RandomTokenError.new(:not_support_case, opt) if opt[:case] != nil
  end
  if opt[:support_friendly]
    if opt[:friendly] || (opt[:friendly] == nil && opt[:mask])
      masked_seed = opt[:seed].dup
      mask = opt[:mask] || MASK
      mask.each { |m| masked_seed.delete(m) }
      opt[:seed] = masked_seed
    elsif opt[:friendly] == false && opt[:mask]
      raise RandomTokenError.new(:false_friendly_with_given_mask, opt)
    end
  else
    if opt[:friendly] == true || opt[:mask] != nil
      raise RandomTokenError.new(:not_support_friendly, opt)
    end
  end
  raise RandomTokenError.new(:mask_remove_all_seeds, opt) if opt[:seed] == []
  if opt[:support_byte] == false && opt[:byte] != nil
    raise RandomTokenError.new(:not_support_byte, opt)
  end
  opt
end