Flexkey
Flexkey is a Ruby gem for generating unique, random strings for use as product keys, redemption codes, invoice numbers, passwords, etc.
Installation
Add this line to your application's Gemfile:
gem 'flexkey'
And then execute:
$ bundle
Or install it yourself as:
$ gem install flexkey
Dependencies
None. Flexkey has been tested with Ruby 1.9.3 and 2.0.
Usage
Basic usage
Instantiate a new generator with Flexkey::Generator.new
and provide a format
and char_pool
. Then, generate a single key or multiple unique keys with the generate
method:
keygen = Flexkey::Generator.new(format: 'aaaa-aa', char_pool: { 'a' => :alpha_upper })
# => #<Flexkey::Generator @format="aaaa-aa", @char_pool={"a"=>:alpha_upper}, @n_possible_keys=308915776>
keygen.generate
# => "KBND-NR"
keygen.generate(3)
# => ["IVXT-LB", "BFZB-LM", "WIVG-ZJ"]
In this example, Flexkey generates a key by replacing each instance of 'a'
in the string 'aaaa-aa'
with a character
randomly drawn from a pool of uppercase letters while leaving unspecified characters (i.e. '-'
) alone.
Since you're most likely persisting generated keys in a database, even though generate(n)
will return n
unique keys, you'll still want to validate them for uniqueness against keys you've previously saved.
Built-in character types
Character type | Description |
---|---|
alpha_upper | uppercase letters |
alpha_lower | lowercase letters |
numeric | numerals |
alpha_upper_clear | alpha_upper without ambiguous letters ("S", "O", etc.) |
alpha_lower_clear | alpha_lower without ambiguous letters ("l", "O", etc.) |
numeric_clear | numeric without ambiguous numerals ("0", "1", and "5") |
symbol | symbols on a standard U.S. keyboard |
basic_symbol | basic symbols on a standard U.S. keyboard |
The names and characters present in each type can be retrieved as such:
Flexkey::CharPool.available_char_types
# => [:alpha_upper, :alpha_lower, :numeric, :alpha_upper_clear, :alpha_lower_clear, :numeric_clear, :symbol, :basic_symbol]
Flexkey::CharPool.available_char_pools
# => {:alpha_upper=>"ABCDEFGHIJKLMNOPQRSTUVWXYZ", :alpha_lower=>"abcdefghijklmnopqrstuvwxyz", :numeric=>"0123456789", :alpha_upper_clear=>"ABCDEFGHJKLMNPQRTUVWXYZ", :alpha_lower_clear=>"abcdefghjkmnpqrtuvwxyz", :numeric_clear=>"2346789", :symbol=>"!@\#$%^&*;:()_+-=[]{}\\|'\",.<>/?", :basic_symbol=>"!@\#$%^&*;:"}
Examples
Flexkey::Generator.new(format: 'a-nnnn', char_pool: {
'a' => :alpha_upper, 'n' => :numeric
}).generate
# => "Y-1145"
Flexkey::Generator.new(format: 'SN-nnnnnnnnn', char_pool: {
'n' => :numeric
}).generate
# => "SN-181073470"
Flexkey::Generator.new(format: 'AA.aa.nn.ss', char_pool: {
'A' => :alpha_upper_clear, 'a' => :alpha_lower_clear, 'n' => :numeric_clear, 's' => :basic_symbol
}).generate
# => "MX.mh.33.*:"
You can also specify a custom string instead of using a built-in type.
Flexkey::Generator.new(format: 'annn/c', char_pool: {
'a' => :alpha_upper, 'n' => :numeric, 'c' => 'LMN'
}).generate(5)
# => ["X905/N", "F865/L", "M423/N", "V564/L", "V874/M"]
Flexkey::Generator.new(format: 'mnnnnnnn', char_pool: {
'm' => '123456789', 'n' => :numeric
}).generate(5)
# => ["45862188", "23054329", "36248220", "56044911", "49873464"]
Selecting from multiple character types
To replace a character in the format
from a pool of multiple character types, specify the both the types and proportions in the char_pool
. For example, to generate keys of length 10 where each character is randomly selected from a pool of uppercase letters and numerals with equal proportions, do the following:
Flexkey::Generator.new(format: '..........', char_pool: {
'.' => { alpha_upper: 0.5, numeric: 0.5 }
}).generate(5)
# => ["OXAEXC2O87", "3D95JXQ60P", "8F28OX31Y8", "65ZY7IM6TL", "B971Q602SO"]
You can specify proportions with any positive numbers:
Flexkey::Generator.new(format: 'U-ccccc-ccccc', char_pool: {
'U' => :alpha_upper_clear, 'c' => { numeric_clear: 1, alpha_upper_clear: 7 }
}).generate(5)
# => ["H-KYLYK-DQLK3", "U-7QUXV-6DXNW", "X-REYAX-LL489", "L-8ABNJ-ZW3A7", "M-TPVTW-VEMTE"]
Flexkey::Generator.new(format: 'UUUUU.LLLLL', char_pool: {
'U' => { 'WXYZ' => 3, 'FGH' => 1 }, 'L' => :alpha_lower_clear
}).generate(5)
# => ["XZYYF.kwkth", "HHFYW.nkpdr", "WXXGW.fvyeu", "HWFXW.xzgeq", "WXWXW.twrdk"]
Number of possible keys
Flexkey will raise an exception if you try to request more keys than are possible with the format
you provided:
keygen = Flexkey::Generator.new(format: 'annn', char_pool: {
'a' => :alpha_upper, 'n' => :numeric
})
keygen.generate(3)
# => ["F202", "U811", "W802"]
keygen.generate(26001)
# Flexkey::GeneratorError: There are only 26000 possible keys
keygen.n_possible_keys
# => 26000
The instance method n_possible_keys
is available for reference as seen above.
Since generate(n)
works by building an array of randomly-generated keys while checking new keys for uniqueness, it's not a good choice for generating all possible keys for a particular format. In that case, it makes more sense to simply build your list of keys iteratively.
CharPool
If you're only interested in using the proportional sampling feature of Flexkey and will generate keys yourself, use Flexkey::CharPool.generate
with a single hash argument:
char_pool = Flexkey::CharPool.generate({ alpha_upper: 0.75, numeric: 0.25 })
10.times.map { char_pool.sample }.join
=> "XC3RPKKWK4"
Additional documentation
At Rubydocs.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request