make_id 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -33
  3. data/lib/make_id/version.rb +1 -1
  4. data/lib/make_id.rb +125 -102
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90cbe0cbac923318d4badd6c848042404633a27c6fbecdd7e2509aee6c31ab5c
4
- data.tar.gz: 41f946d9367bb73257ac31ffce792bd309f2e707c44b39003d66dcc3d1890a49
3
+ metadata.gz: 2448e655a9a006abb23272b2b54c6b4fc537f702407c931afcf106b82c468b04
4
+ data.tar.gz: 9852758f34e12c2be8aa90149cdded09e011f2ab879320089fc1bfb3f577d849
5
5
  SHA512:
6
- metadata.gz: da8822e1194eb4ed1e51f1090f120db17cdd421fc330f84dbe4b4556c1dd71eac4dc33dff678768999cee03ad21749a9f3bbb5a2949ced4f83c7f7afd802128a
7
- data.tar.gz: '038ae0b3bc50252cd75eec5fb7283feb27381e3362bd2681fbba6ff225865727ef4fa560f84d24e8c4703f5ba96ce168c9278462b9469b97323ab981869e387d'
6
+ metadata.gz: 108e40b61bfdcc00ac5e550b4afb14fb8f7298df617d10b7179975b2be8f6f04c6b4693fc6909de26f42e6a9977333d12f7ecc5c5846b1317b3ab728b6e6d04d
7
+ data.tar.gz: 25c7229af03bc353707c2ee832f00c2ad63243318156ffa51bcd197f328a2cae865eaf37fa0949d7c8d98bcf9e583b4ec8f2fb2563317d7584b906b9f3c8cf08
data/README.md CHANGED
@@ -40,18 +40,19 @@ numeric codes.
40
40
 
41
41
  Bases supported are:
42
42
 
43
- - Base62: digits, upper, and lower-case letters. No special characters
43
+ - Base94: Base64 (Upper, Lower, Digits) with 30 extra special characters
44
+ - Base64: Url-Safe version. Base64 but swaps the plus and slash by dash and underscore respectively.
45
+ - Base62: digits, upper, and lower-case letters. No special characters. The default.
44
46
  - Base32: digits and upper case without ambiguous characters "1lI" or "oO0"
45
47
  - Base 2 through 36 (except 32): Ruby's `Integer#to_s(base)` is used
46
- - Base64: Uses the `Base64.urlsafe_encode64` such has 2 special characters.
47
- - Base63: It is not implemented.
48
48
 
49
- The Base32 may seem out of place, but is useful for alpha-numeric codes the users are required to type, such as redemption codes.
50
- All letter are folded to upper-case, and ambiguous characters are converted to the canonical ones.
49
+ The Base32 may seem out of place, but is useful for alpha-numeric codes the users are required to type or speak,
50
+ such as serial numbers or license codes.
51
+ All letters are upper-case, and ambiguous characters are converted to the canonical ones.
51
52
 
52
- MakeId.int_to_base(123456789, 32) #=> "3nqk8n"
53
- MakeId.from_base("3nqk8n", 10) #=> 123456789
54
- MakeId.int_to_base(123456789, 32) #=> "3nqk8n"
53
+ MakeId.int_to_base(123456789, 32) #=> "3NQK8N"
54
+ MakeId.from_base("3NQK8N", 10) #=> 123456789
55
+ MakeId.int_to_base(123456789, 32) #=> "3NQK8N"
55
56
  MakeId.verify_base32_id("...") #=> corrected_id or nil if error
56
57
 
57
58
  ### Random Integer
@@ -60,8 +61,14 @@ MakeId can return a random (8-byte by default) integer. You can request it retur
60
61
  and with an optional check_digit.
61
62
  Usually, you would use the integer returned, and call `int_to_base` to format for a URL or code.
62
63
 
63
- MakeId.random_id() #=> 15379918763975837985ZZ
64
- MakeId.random_id(base: 62, check_digit: true) #=> "2984biEwRT1"
64
+ MakeId.id() #=> 15379918763975837985ZZ
65
+ MakeId.id(base: 62, check_digit: true) #=> "2984biEwRT1"
66
+
67
+ Nano Id's are shorter unique strings generated from random characters, usually as a friendlier alternative
68
+ to UUID's. These are 8-byte numeric identifiers in extended bases, such as 36 or 62.
69
+
70
+ MakeId.nano_id() #=> "iZnLn96FVcjivEJA" (Base-62 be default)
71
+ MakeId.nano_id(base: 36) #=> "sf8kqb8ekn7k98rq"
65
72
 
66
73
  ### UUID
67
74
 
@@ -75,16 +82,28 @@ can be used to transform a long UUID into a possibly more palettable base repres
75
82
  MakeId.uuid_to_base(u, 62) #=> "fWJtuXEQJnkjxroWjkmei" (21 characters)
76
83
 
77
84
  Note that some databases support a UUID type which makes storing UUID's easier, and since they are stored as a binary
78
- field, consume less space.ZZ
85
+ field, consume less space.
79
86
 
80
- ### Nano Id
87
+ ### Tokens
81
88
 
82
- Nano Id's are shorter unique strings generated from random characters, usually as a friendlier alternative
83
- to UUID's. They also can be of any size, depending on the key range you require. Pay attention to the keyspace,
84
- ensuring you have enough characters to avoid predictable collisions in the future.
89
+ Tokens are randomly-generated strings of the character set of the requested base.
90
+ The default size is 16 characters of the Base-62 character set.
91
+
92
+ MakeId.token() #=> "Na4VX61PBFVZWL6Y"
93
+ MakeId.token(8, base:36) #=> "BK0ZTL9H"
94
+
95
+ ### Codes
85
96
 
86
- MakeId.nano_id(size: 16) #=> "iZnLn96FVcjivEJA"
87
- MakeId.nano_id(size: 16, base: 32) #=> "sf8kqb8ekn7k98rq"
97
+ Codes are string tokens to send to users for input. They have no ambiguous characters to avoid confusion.
98
+ This is useful for verifications such as two-factor authentication codes, or license numbers.
99
+ This returns an 8-character string by default. Specify a group (size) and delimiter (default is a hyphen)
100
+ to make long codes readable.
101
+
102
+ MakeId.code #=> "22E0D18F"
103
+ MakeId.code(20) #=> "Y41Q24AG7DYZYTAZWQZX"
104
+ MakeId.code(20, group: 4, delimiter: "-") #=> "9975-V5VM-KKSR-4PQ6-7F4G"
105
+
106
+ ### Temporal Identifiers
88
107
 
89
108
  A `request_id` is a nano_id that can be used to track requests and jobs. It is a 16-byte string, the same
90
109
  storage as a UUID, but with columnar values. The substring of 3 for 8 is a short (8 character) version that
@@ -95,9 +114,7 @@ can be used as well, is easier to read, sortable within a day, and unique enough
95
114
  id[3,8] #=> "f1272t01"
96
115
  #-------------------------->Hsssuuqq
97
116
 
98
- ### Snowflake Id
99
-
100
- Snowflakes were invented at Twitter to stamp an identifier for a tweet or direct message.
117
+ Snowflake Id's were invented at Twitter to stamp an identifier for a tweet or direct message.
101
118
  It is an 8-byte integer intended to be time-sorted and unique across the fleet of servers saving messages.
102
119
  It is a bit-mapped integer consisting of these parts:
103
120
 
@@ -120,7 +137,7 @@ You can also pass in options to return it as a different base, and with a check
120
137
 
121
138
  MakeId.app_worker_id = 234
122
139
  MakeId.snowflake_id => 618905333721374720
123
- MakeId.snowflake_id(worker_id: 12, base: 32, sequence_method: :random) #=> "2tmxk6ne81jd5"
140
+ MakeId.snowflake_id(worker_id: 12, base: 32, sequence_method: :random) #=> "2TMXK6NE81JD5"
124
141
 
125
142
  The `snowflake_uuid` method provides a time-based identifier, great for sorting just as sequential numbers, but unique enough to fit the bill.
126
143
 
@@ -136,18 +153,6 @@ records or when you need a slowflake ID but have a UUID column to fill.
136
153
  MakeID.snowflake_datetime_uuid #=> "20240904-1418-5332-2000-3a38e61d5582"
137
154
  #------------------------>YYYYMMDD-hhmm-ssuu-uwww-rrrrrrrrrrrr
138
155
 
139
- ## Experimental Id's
140
-
141
- The `event_id` is a string, sortable by creation time, with visible time seperator columns.
142
- It is of the format "YMDhmsuurrrr", using Base62, with an optional check_sum characer.
143
- It also used the application epoch described under `snowflake_id`. "uu" represents the fractional
144
- seconds that can be represented in Base62, and a 4-character random Base64 "nano_id".
145
-
146
- MakeId.epoch = 2020
147
- MakeId.event_id #=> "493KgpQGErTB"
148
- #------------------->YMDhmsuurrrr ()
149
- MakeId.event_id(check_digit: true) #=> "493Kkha6HZa2" (3 random chars + check digit)
150
-
151
156
  ## Development
152
157
 
153
158
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MakeId
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/make_id.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative "make_id/version"
4
4
  require "securerandom"
5
- require "base64"
6
5
  require "zlib"
7
6
 
8
7
  # MakeID generates record Identifiers other than sequential integers.
@@ -11,10 +10,27 @@ require "zlib"
11
10
  # Adopt - Copy this file to your application with the above attribution to
12
11
  # allow others to find fixes, documentation, and new features.
13
12
  module MakeId
14
- # class Error < StandardError; end
13
+ class Error < StandardError; end
15
14
 
16
- CHARS32 = "0123456789abcdefghjkmnpqrstvwxyz" # Avoiding ambiguous 0/o i/l/I
17
- CHARS62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
15
+ # Base32 avoids ambiguous letters for 0/o/O and i/I/l/1. This is useful
16
+ # for human-interpreted codes for serial numbers, license keys, etc.
17
+ BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
18
+
19
+ # Ruby's Integer.to_s(2..36) uses extended Hexadecimal: 0-9,a-z.
20
+ # Base62 includes upper-case letters as well, maintaining ASCII cardinality.
21
+ BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
22
+
23
+ # Base64 Does not use ASCII-collating (sort) character set
24
+ BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
25
+
26
+ # Base94 extends Base64 with all printable ASCII special characters.
27
+ # Using Base of 90 won't use quotes, backslash
28
+ BASE94 = BASE64 + %q(!$%&()*,-.:;<=>?@[]^_{|}~#`'"\\)
29
+
30
+ # URL-Encoded Base64 swaps the + and / for - and _ respectively to avoid URL Encoding
31
+ URL_BASE64 = BASE64.tr("+/", "-_")
32
+
33
+ # TWitter Snowflake starts its epoch at this time.
18
34
  EPOCH_TWITTER = Time.utc(2006, 3, 21, 20, 50, 14)
19
35
 
20
36
  @@app_worker_id = ENV.fetch("APP_WORKER_ID", 0)
@@ -57,31 +73,11 @@ module MakeId
57
73
  end
58
74
 
59
75
  ##############################################################################
60
- # Random Strings
61
- ##############################################################################
62
-
63
- # Returns a random alphanumeric string of the given base, default of 62.
64
- # Base 64 uses URL-safe characters. Bases 19-32 and below use a special
65
- # character set that avoids visually ambiguous characters. Other bases
66
- # utilize the full alphanumeric characer set (digits, lower/upper letters).
67
- def self.random(size = 16, base: 62)
68
- raise "Base must be between 2 and 62, or 64, not #{base}" unless base < 63 || base == 64
69
- if base == 62
70
- SecureRandom.alphanumeric(size)
71
- elsif base == 64
72
- SecureRandom.urlsafe_base64(size)
73
- else
74
- alpha = (base <= 32) ? CHARS32 : CHARS62
75
- (1..size).map { alpha[SecureRandom.rand(base - 1)] }.join
76
- end
77
- end
78
-
79
- ##############################################################################
80
- # Integers
76
+ # Numeric Identifiers (of any suported base)
81
77
  ##############################################################################
82
78
 
83
79
  # Random Integer ID
84
- def self.random_id(bytes: 8, base: 10, absolute: true, check_digit: false)
80
+ def self.id(bytes: 8, base: 10, absolute: true, check_digit: false)
85
81
  id = SecureRandom.random_number(2**(bytes * 8) - 2) + 1 # +1 to avoid zero
86
82
  id = id.abs if absolute
87
83
  id = int_to_base(id, base) unless base == 10
@@ -89,11 +85,26 @@ module MakeId
89
85
  id
90
86
  end
91
87
 
88
+ def self.id_password(bytes: 8, base: 10, absolute: true, alpha: nil)
89
+ id = id(bytes: bytes)
90
+ pass = id(bytes: 16)
91
+ [int_to_base(id, base), encode_alphabet(pass, alpha || BASE94, seed: id)]
92
+ end
93
+
94
+ # Generates a 8-byte "nano id", a string of random characters of the given alphabet,
95
+ # suitable for URL's or where you don't want to show a sequential number.
96
+ # A check digit can be added to the end to help prevent typos.
97
+ def self.nano_id(bytes: 8, base: 62, check_digit: true)
98
+ bytes -= 1 if check_digit
99
+ id = id(bytes: bytes, base: base)
100
+ check_digit ? append_check_digit(id, base) : id
101
+ end
102
+
92
103
  ##############################################################################
93
104
  # UUID - Universally Unique Identifier
94
105
  ##############################################################################
95
106
 
96
- # Returns a (securely) random generated UUID v4
107
+ # Returns a 16-byte securely-random generated UUID v4
97
108
  def self.uuid
98
109
  SecureRandom.uuid
99
110
  end
@@ -106,66 +117,57 @@ module MakeId
106
117
  end
107
118
 
108
119
  ##############################################################################
109
- # Nano Id - Simple, secure URL-friendly unique string ID generator
120
+ # Strings Identifiers
110
121
  ##############################################################################
111
122
 
112
- # Generates a "nano id", a string of random characters of the given alphabet,
113
- # suitable for URL's or where you don't want to show a sequential number.
114
- # A check digit is added to the end to help prevent typos.
115
- def self.nano_id(size: 20, base: 62, check_digit: true)
116
- # alpha = (base <= 32) ? CHARS32 : CHARS62
117
- size -= 1 if check_digit
118
- id = random(size, base: base)
119
- check_digit ? append_check_digit(id, base) : id
120
- end
121
-
122
- # Given a nano_id, replaces visually ambiguous characters and verifies the
123
- # check digit. Returns the corrected id or nil if the check digit is invalid.
124
- def self.verify_base32_id(nanoid)
125
- nanoid.gsub!(/[oO]/, "0")
126
- nanoid.gsub!(/[lLiI]/, "1")
127
- nanoid.downcase
128
- valid_check_digit?(nanoid, base: 32)
123
+ # Returns a random alphanumeric string of the given base, default of 62.
124
+ # Base 64 uses URL-safe characters. Bases 19-32 and below use a special
125
+ # character set that avoids visually ambiguous characters. Other bases
126
+ # utilize the full alphanumeric characer set (digits, lower/upper letters).
127
+ def self.token(size = 16, base: 62, chars: nil)
128
+ _, chars = base_characters(base, chars)
129
+ SecureRandom.alphanumeric(size, chars: chars.chars)
129
130
  end
130
131
 
131
- # Manual Id is a code and/or identifier that is manually entered by a user.
132
- # Examples of this would be a Two-Factor Authentication challenge, a code
133
- # used for confirmation, redemption, or a short-term record lookup code
134
- # (like an airline ticket/itenerary code)
135
- # It uses a base-32 (non-ambiguous character set) by default,
136
- def self.manual_id(size: 6, base: 32, check_digit: false)
137
- base = 32 if base > 36 # For upcasing
138
- nano_id(size: size, base: base, check_digit: check_digit).upcase
132
+ # Returns a new, ramdonly-generated Base-32 code (no ambiguous characters).
133
+ # Use this for Two-Factor Authorization, and serial number codes to be
134
+ # input by users. Use verify_code() to "fix" user-input of codes.
135
+ def self.code(size = 8, group: 0, delimiter: "-")
136
+ id = token(size, base: 32)
137
+ id = id.chars.each_slice(group).map(&:join).join(delimiter) if group > 0
138
+ id
139
139
  end
140
140
 
141
- def self.fix_manual_id(id, base: 32, check_digit: false)
142
- if base == 32
143
- id = id.gsub(/[oO]/, "0")
144
- id = id.gsub(/[lLiI]/, "1")
145
- end
146
- id = valid_check_digit?(id.downcase, base: 32) if check_digit
147
- id.upcase
141
+ # Given a nano_id, replaces visually ambiguous characters and verifies the
142
+ # check digit. Returns the corrected id or nil if the check digit is invalid.
143
+ def self.verify_code(nanoid, check_digit: false)
144
+ nanoid = nanoid.gsub(/\W/, "")
145
+ nanoid = nanoid.gsub(/[oO]/, "0")
146
+ nanoid = nanoid.gsub(/[lLiI]/, "1")
147
+ nanoid = nanoid.upcase
148
+ return valid_check_digit?(nanoid, base: 32) if check_digit
149
+ nanoid
148
150
  end
149
151
 
150
152
  ##############################################################################
151
- # Event Id - A nano_id, but timestamped event identifier: YMDHMSUUrrrrc
153
+ # TEMPORAL Identifiers
152
154
  ##############################################################################
153
155
 
154
- # Returns an event timestamp of the form YMDHMSUUrrrrc
156
+ # Event Id - A nano_id, but timestamped event identifier: YMDHMSUUrrrrc
155
157
  def self.event_id(size: 12, check_digit: false, time: nil)
156
158
  time ||= Time.new.utc
157
159
  usec = int_to_base((time.subsec.to_f * 62 * 62).to_i, 62)
158
160
  parts = [
159
- CHARS62[time.year % @@epoch.year],
160
- CHARS62[time.month],
161
- CHARS62[time.day],
162
- CHARS62[time.hour],
163
- CHARS62[time.min],
164
- CHARS62[time.sec],
161
+ BASE62[time.year % @@epoch.year],
162
+ BASE62[time.month],
163
+ BASE62[time.day],
164
+ BASE62[time.hour],
165
+ BASE62[time.min],
166
+ BASE62[time.sec],
165
167
  usec.rjust(2, "0") # 2-chars, 0..3843
166
168
  ]
167
169
  nano_size = size - 8 - (check_digit ? 1 : 0)
168
- parts << nano_id(size: nano_size, base: 62) if nano_size > 0
170
+ parts << token(nano_size, base: 62) if nano_size > 0
169
171
  id = check_digit ? append_check_digit(parts.join, 62) : parts.join
170
172
  id[0, size]
171
173
  end
@@ -183,15 +185,15 @@ module MakeId
183
185
  end
184
186
 
185
187
  [
186
- CHARS62[time.year % @@epoch.year],
187
- CHARS62[time.month],
188
- CHARS62[time.day], # "-",
189
- CHARS62[time.hour].downcase,
188
+ BASE62[time.year % @@epoch.year],
189
+ BASE62[time.month],
190
+ BASE62[time.day], # "-",
191
+ BASE62[time.hour].downcase,
190
192
  int_to_base(seconds, 32).rjust(3, "0"), # 3 chars
191
193
  int_to_base((time.subsec.to_f * 32 * 32).to_i, 32), # 2 chars
192
194
  sequence.to_s(32).rjust(2, "0"), # 2 chars "-",
193
195
  (app_worker_id % 1024).to_s(32).rjust(2, "0"), # 2 chars
194
- random(3, base: 32)
196
+ token(3, base: 32)
195
197
  ].join
196
198
  end
197
199
 
@@ -298,23 +300,9 @@ module MakeId
298
300
  # Ruby's int.to_s(base) only goes to 36. Base 32 is special as it does not
299
301
  # contain visually ambiguous characters (1, not i, I, l, L) and (0, not o or O)
300
302
  # Which is useful for serial numbers or codes the user has to read or type
301
- def self.int_to_base(int, base = 62, check_digit: false)
302
- int = int.to_i
303
- if base == 10
304
- id = int.to_s
305
- elsif base == 64
306
- id = Base64.urlsafe_encode64(int.to_s).delete("=")
307
- elsif base == 32 || base > 36
308
- alpha = (base <= 32) ? CHARS32 : CHARS62
309
- id = ""
310
- while int > (base - 1)
311
- id = alpha[int % base] + id
312
- int /= base
313
- end
314
- id = alpha[int] + id
315
- else
316
- id = int.to_s(base)
317
- end
303
+ def self.int_to_base(int, base = 62, check_digit: false, chars: nil)
304
+ base, chars = base_characters(base, chars)
305
+ id = encode_alphabet(int, chars)
318
306
  check_digit ? append_check_digit(id, base) : id
319
307
  end
320
308
 
@@ -322,21 +310,55 @@ module MakeId
322
310
 
323
311
  # Parses a string as a base n number and returns its decimal integer value
324
312
  def self.base_to_int(string, base = 62, check_digit: false)
325
- # TODO check_digit
326
- if base == 64
327
- int = Base64.urlsafe_decode64(string.to_s + "==")
328
- elsif base == 32 || base > 36
329
- alpha = (base <= 32) ? CHARS32 : CHARS62
330
- string = string.to_s
331
- int = 0
332
- string.each_char { |c| int = int * base + alpha.index(c) }
333
- else
334
- int = string.to_i(base)
313
+ # TODO: check_digit
314
+ _, chars = base_characters(base, chars)
315
+ decode_alphabet(string, chars)
316
+ end
317
+
318
+ singleton_class.alias_method :from_base, :base_to_int
319
+
320
+ def self.encode_alphabet(int, alpha = BASE62, seed: nil)
321
+ base = alpha.size
322
+ alpha = alpha.chars.shuffle(random: Random.new(seed)).join if seed
323
+ id = ""
324
+ while int > (base - 1)
325
+ id = alpha[int % base] + id
326
+ int /= base
335
327
  end
328
+ alpha[int] + id
329
+ end
330
+
331
+ def self.decode_alphabet(string, alpha = BASE32, seed: nil, base: nil)
332
+ base ||= alpha.size
333
+ alpha = alpha.chars.shuffle(random: Random.new(seed)).join if seed
334
+ int = 0
335
+ string.each_char { |c| int = int * base + alpha.index(c) }
336
336
  int
337
+ rescue
338
+ nil
337
339
  end
338
340
 
339
- singleton_class.alias_method :from_base, :base_to_int
341
+ # Returns the refined base and characters used for the base conversions
342
+ def self.base_characters(base, chars = nil, shuffle_seed: nil)
343
+ if chars
344
+ base ||= chars.size
345
+ chars = chars[0..(base - 1)]
346
+ elsif base > 94 || base < 2
347
+ raise Error.new("Base#{base} is not supported")
348
+ elsif base > 64
349
+ chars = BASE94[0..(base - 1)]
350
+ elsif base > 62
351
+ chars = URL_BASE64[0..(base - 1)]
352
+ elsif base == 32
353
+ chars = BASE32
354
+ else
355
+ chars = BASE62[0..(base - 1)]
356
+ end
357
+ chars = chars.chars.shuffle(random: Random.new(shuffle_seed)).join if shuffle_seed
358
+ base = chars.size
359
+
360
+ [base, chars]
361
+ end
340
362
 
341
363
  ##############################################################################
342
364
  # Check Digit
@@ -352,6 +374,7 @@ module MakeId
352
374
  # Uses a pre-defined check_proc if configured. See check_proc=().
353
375
  def self.compute_check_digit(id, base = 10)
354
376
  return @@check_proc.call(id, base) if @@check_proc.is_a?(Proc)
377
+
355
378
  int_to_base(Zlib.crc32(id.to_s) % base, base)
356
379
  end
357
380
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: make_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Allen Fair
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-13 00:00:00.000000000 Z
11
+ date: 2024-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64