Module: RandomToken

Defined in:
lib/random_token.rb,
lib/random_token/version.rb,
lib/random_token/random_token_error.rb

Defined Under Namespace

Classes: RandomTokenError

Constant Summary

NUMBERS =

The number seed

('0'..'9')
ALPHABETS =

The alphabet seed

('A'..'Z')
MASK =

The default friendly mask

['1', 'I', 'l', 'i', '0', 'O', 'o', 'Q', 'D',
'C', 'c', 'G', '9', '6', 'U', 'u', 'V', 'v',
'E', 'F', 'M', 'N', '8', 'B']
DEFAULT_OPT =

The default option definition

{
  :seed => nil,
  :friendly => false,
  :case => :mixed
}
SEED_TYPES =

The default seeds definition

{
  :default => {
    :abbr => [nil],
    :seed => [NUMBERS, ALPHABETS],
    :support_friendly => true,
    :support_case => true,
    :default_case => :mixed,
    :support_byte => false,
    :byte_mult => 1
  },
  :alphabet => {
    :abbr => [:letter, :a, :l],
    :seed => [ALPHABETS]
  },
  :number => {
    :abbr => [:n, 1, 10],
    :seed => [NUMBERS],
    :support_case => false
  },
  :binary => {
    :abbr => [:b, 2],
    :seed => [('0'..'1')],
    :support_case => false,
    :support_friendly => false,
    :support_byte => true,
    :byte_mult => 16
  },
  :oct => {
    :abbr => [:o, 8],
    :seed => [('0'..'7')],
    :support_case => false,
    :support_friendly => false,
    :support_byte => true,
    :byte_mult => 4
  },
  :hex => {
    :abbr => [:h, 16],
    :seed => [NUMBERS, ('A'..'F')],
    :support_friendly => false,
    :default_case => :up,
    :support_byte => true,
    :byte_mult => 2
  }
}
SUPPORTED_OPTS =

The supported options

{
  :seed => {
    :abbr => :s
  },
  :case => {
    :abbr => :c,
    :value => [:up, :u, :down, :d, :mixed, :m]
  },
  :mask => {
    :abbr => :m
  },
  :friendly => {
    :abbr => :f,
    :value => [true, false]
  },
  :byte => {
    :abbr => :b,
    :value => [true, false]
  }
}
STRF_ARG_MAP =

The directives used in the format string

{
  'A' => { :seed => :alphabet, :case => :up },
  'a' => { :seed => :alphabet, :case => :down },
  'n' => { :seed => :number },
  'b' => { :seed => :binary },
  'o' => { :seed => :oct },
  'h' => { :seed => :hex, :case => :down },
  'H' => { :seed => :hex, :case => :up },
  'X' => { :case => :up },
  'x' => { :case => :down },
  '?' => {}
}
VERSION =
'1.1.0'

Class Method Summary (collapse)

Class Method Details

+ (Object) arg_dispatcher(arg, options, count = false) (private)

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



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# 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?(Fixnum)
    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

+ (Object) check_opt(opts) (private)

Check options



259
260
261
262
263
264
265
266
267
268
269
270
# 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

+ (String) gen(arg, options = {})

The major method to generate a random token.

Parameters:

  • arg (Fixnum, String)

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

  • options (Hash) (defaults to: {})

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

Returns:

  • (String)

    The generated token.

Raises:



118
119
120
121
122
# 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

+ (Object) gen_seeds(opt) (private)

Generate seeds according to the :seed options



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# 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

+ (String) genf(arg, options = {})

A convenient method to generate a friendly token. It would call gen with :friendly => true option.

Parameters:

  • arg (Fixnum, String)

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

  • options (Hash) (defaults to: {})

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

Returns:

  • (String)

    The generated token.

Raises:



129
130
131
# File 'lib/random_token.rb', line 129

def genf(arg, options = {})
  gen(arg, { :friendly => true }.merge(options))
end

+ (String) get(arg, options = {})

An old method for downward compatibility and it should be discarded. Use “gen” instead.

Parameters:

  • arg (Fixnum, String)

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

  • options (Hash) (defaults to: {})

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

Returns:

  • (String)

    The generated token.

Raises:



153
154
155
# File 'lib/random_token.rb', line 153

def get(arg, options = {})
  gen(arg, options)
end

+ (Object) run_by_length(length, options) (private)

Generate/count token with a given length.



199
200
201
202
203
204
205
206
207
208
209
# 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

+ (Object) run_by_pattern(pattern, options = {}) (private)

Generate/count token with a format string.



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# 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

+ (Object) seed_modifier(opt) (private)

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

Raises:



301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# 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

+ (String) strf(arg, options = {})

An old method for downward compatibility and it should be discarded. Use “gen” instead.

Parameters:

  • arg (Fixnum, String)

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

  • options (Hash) (defaults to: {})

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

Returns:

  • (String)

    The generated token.

Raises:



163
164
165
# File 'lib/random_token.rb', line 163

def strf(arg, options = {})
  gen(arg, options)
end