ruby-ulid 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -75
- data/lib/ulid/version.rb +1 -1
- data/lib/ulid.rb +36 -8
- data/sig/ulid.rbs +54 -8
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d7356366d0184815a725d1947f4f685b3abba0320ae60800b5a015dc7c649e9
|
4
|
+
data.tar.gz: 04b55b6d92dbf02865a7803be352f5cd385f3417c061269f2ad197474202154d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa826d204cbdc1e6850fbeab278dc72e5b683926db9af7ed477ec2e74837d32829dbfb468c1156d6dcf5be604f9fdeb8fd0a282999b47a627884152b2a2cd5d4
|
7
|
+
data.tar.gz: 0b1208e76af50f9952c8c4835d1410c7e1fd114313cc71d39a143c9bc04ac4f1a35ba49be88a49406606c441e4f4fa7cad5fc938d74fcecde0d612319a6890b3
|
data/README.md
CHANGED
@@ -7,8 +7,7 @@
|
|
7
7
|
|
8
8
|
[ulid/spec](https://github.com/ulid/spec) is useful.
|
9
9
|
Especially possess all `uniqueness`, `randomness`, `extractable timestamps` and `sortable` features.
|
10
|
-
This gem aims to provide the generator,
|
11
|
-
Also providing [RBS](https://github.com/ruby/rbs) signatures.
|
10
|
+
This gem aims to provide the generator, optional monotonicity, parser and other manipulation features around ULID with included [RBS](https://github.com/ruby/rbs).
|
12
11
|
|
13
12
|
---
|
14
13
|
|
@@ -50,7 +49,7 @@ Should be installed!
|
|
50
49
|
Add this line in your Gemfile.
|
51
50
|
|
52
51
|
```ruby
|
53
|
-
gem('ruby-ulid', '~> 0.
|
52
|
+
gem('ruby-ulid', '~> 0.5.0')
|
54
53
|
```
|
55
54
|
|
56
55
|
### How to use
|
@@ -58,8 +57,8 @@ gem('ruby-ulid', '~> 0.4.0')
|
|
58
57
|
```ruby
|
59
58
|
require 'ulid'
|
60
59
|
|
61
|
-
|
62
|
-
# => "
|
60
|
+
ULID::VERSION
|
61
|
+
# => "0.5.0"
|
63
62
|
```
|
64
63
|
|
65
64
|
### Basic Generator
|
@@ -72,7 +71,7 @@ ulid = ULID.generate #=> ULID(2021-04-27 17:27:22.826 UTC: 01F4A5Y1YAQCYAYCTC7GR
|
|
72
71
|
|
73
72
|
### Parser
|
74
73
|
|
75
|
-
|
74
|
+
Get the objects from exists encoded ULIDs.
|
76
75
|
|
77
76
|
```ruby
|
78
77
|
ulid = ULID.parse('01ARZ3NDEKTSV4RRFFQ69G5FAV') #=> ULID(2016-07-30 23:54:10.259 UTC: 01ARZ3NDEKTSV4RRFFQ69G5FAV)
|
@@ -80,7 +79,7 @@ ulid = ULID.parse('01ARZ3NDEKTSV4RRFFQ69G5FAV') #=> ULID(2016-07-30 23:54:10.259
|
|
80
79
|
|
81
80
|
### ULID object
|
82
81
|
|
83
|
-
|
82
|
+
Extract timestamps and binary formats.
|
84
83
|
|
85
84
|
```ruby
|
86
85
|
ulid = ULID.parse('01F4A5Y1YAQCYAYCTC7GRMJ9AA') #=> ULID(2021-04-27 17:27:22.826 UTC: 01F4A5Y1YAQCYAYCTC7GRMJ9AA)
|
@@ -120,7 +119,7 @@ end
|
|
120
119
|
ulids.sort == ulids #=> true
|
121
120
|
```
|
122
121
|
|
123
|
-
|
122
|
+
Basic generator prefers `randomness`, it does not guarantee `sortable` for same milliseconds ULIDs.
|
124
123
|
|
125
124
|
```ruby
|
126
125
|
ulids = 10000.times.map do
|
@@ -202,7 +201,7 @@ time = Time.at(946684800, Rational('123456.789')).utc #=> 2000-01-01 00:00:00.12
|
|
202
201
|
ULID.floor(time) #=> 2000-01-01 00:00:00.123 UTC
|
203
202
|
```
|
204
203
|
|
205
|
-
###
|
204
|
+
### Tools
|
206
205
|
|
207
206
|
#### Scanner for string (e.g. `JSON`)
|
208
207
|
|
@@ -341,31 +340,32 @@ ULID.sample(5, period: ulid1.to_time..ulid2.to_time)
|
|
341
340
|
|
342
341
|
I'm afraid so, we should consider [Current ULID spec](https://github.com/ulid/spec/tree/d0c7170df4517939e70129b4d6462cc162f2d5bf#universally-unique-lexicographically-sortable-identifier) has `orthographical variants of the format` possibilities.
|
343
342
|
|
343
|
+
>Case insensitive
|
344
|
+
|
345
|
+
I can understand it might be considered in actual use-case. So `ULID.parse` accepts upcase and downcase.
|
346
|
+
However it is a controversial point, discussing in [ulid/spec#3](https://github.com/ulid/spec/issues/3).
|
347
|
+
|
344
348
|
>Uses Crockford's base32 for better efficiency and readability (5 bits per character)
|
345
349
|
|
346
350
|
The original `Crockford's base32` maps `I`, `L` to `1`, `O` to `0`.
|
347
351
|
And accepts freestyle inserting `Hyphens (-)`.
|
348
352
|
To consider this patterns or not is different in each implementations.
|
349
353
|
|
350
|
-
|
351
|
-
I have suggested it would be clarified in [ulid/spec#57](https://github.com/ulid/spec/pull/57).
|
352
|
-
|
353
|
-
>Case insensitive
|
354
|
-
|
355
|
-
I can understand it might be considered in actual use-case.
|
356
|
-
But it is a controversial point, discussing in [ulid/spec#3](https://github.com/ulid/spec/issues/3).
|
354
|
+
I have suggested to clarify `subset of Crockford's base32` in [ulid/spec#57](https://github.com/ulid/spec/pull/57).
|
357
355
|
|
358
|
-
|
356
|
+
This gem provides some methods to handle the nasty possibilities.
|
359
357
|
|
360
|
-
`ULID.normalize` and `ULID.
|
358
|
+
`ULID.normalize`, `ULID.normalized?`, `ULID.valid_as_variant_format?` and `ULID.parse_variant_format`
|
361
359
|
|
362
360
|
```ruby
|
363
|
-
ULID.normalize('-
|
364
|
-
ULID.normalized?('-
|
365
|
-
ULID.normalized?('
|
361
|
+
ULID.normalize('01g70y0y7g-z1xwdarexergsddd') #=> "01G70Y0Y7GZ1XWDAREXERGSDDD"
|
362
|
+
ULID.normalized?('01g70y0y7g-z1xwdarexergsddd') #=> false
|
363
|
+
ULID.normalized?('01G70Y0Y7GZ1XWDAREXERGSDDD') #=> true
|
364
|
+
ULID.valid_as_variant_format?('01g70y0y7g-z1xwdarexergsddd') #=> true
|
365
|
+
ULID.parse_variant_format('01G70Y0Y7G-ZLXWDIREXERGSDoD') #=> ULID(2022-07-03 02:25:22.672 UTC: 01G70Y0Y7GZ1XWD1REXERGSD0D)
|
366
366
|
```
|
367
367
|
|
368
|
-
#### UUIDv4 converter
|
368
|
+
#### UUIDv4 converter (experimental)
|
369
369
|
|
370
370
|
`ULID.from_uuidv4` and `ULID#to_uuidv4` is the converter.
|
371
371
|
The imported timestamp is meaningless. So ULID's benefit will lost.
|
@@ -398,68 +398,19 @@ ULID.min == reversed_min #=> false
|
|
398
398
|
ULID.max == reversed_max #=> false
|
399
399
|
```
|
400
400
|
|
401
|
-
##
|
402
|
-
|
403
|
-
As far as I know, major prior arts are below
|
404
|
-
|
405
|
-
### [ulid gem](https://rubygems.org/gems/ulid) - [rafaelsales/ulid](https://github.com/rafaelsales/ulid)
|
406
|
-
|
407
|
-
It is just providing basic `String` generator only.
|
408
|
-
So you can replace the code as below
|
409
|
-
|
410
|
-
```diff
|
411
|
-
-ULID.generate
|
412
|
-
+ULID.generate.to_s
|
413
|
-
```
|
414
|
-
|
415
|
-
NOTE: In version before `1.3.0`, timestamps might not be correct value.
|
416
|
-
|
417
|
-
1. [Sort order does not respect millisecond ordering](https://github.com/rafaelsales/ulid/issues/22)
|
418
|
-
1. [Fixed in this PR](https://github.com/rafaelsales/ulid/pull/23)
|
419
|
-
1. [Released in 1.3.0](https://github.com/rafaelsales/ulid/compare/1.2.0...v1.3.0)
|
420
|
-
|
421
|
-
### [ulid-ruby gem](https://rubygems.org/gems/ulid-ruby) - [abachman/ulid-ruby](https://github.com/abachman/ulid-ruby)
|
422
|
-
|
423
|
-
It is providing basic generator(except monotonic generator) and parser.
|
424
|
-
Major methods can be replaced as below.
|
425
|
-
|
426
|
-
```diff
|
427
|
-
-ULID.generate
|
428
|
-
+ULID.generate.to_s
|
429
|
-
-ULID.at(time)
|
430
|
-
+ULID.at(time).to_s
|
431
|
-
-ULID.time(string)
|
432
|
-
+ULID.parse(string).to_time
|
433
|
-
-ULID.min_ulid_at(time)
|
434
|
-
+ULID.min(time).to_s
|
435
|
-
-ULID.max_ulid_at(time)
|
436
|
-
+ULID.max(time).to_s
|
437
|
-
```
|
438
|
-
|
439
|
-
NOTE: In version before `1.0.2`, timestamps might not be correct value.
|
440
|
-
|
441
|
-
1. [Parsed time object has more than milliseconds](https://github.com/abachman/ulid-ruby/issues/3)
|
442
|
-
1. [Fix to handle timestamp precision in parser](https://github.com/abachman/ulid-ruby/pull/5)
|
443
|
-
1. [Fix to handle timestamp precision in generator](https://github.com/abachman/ulid-ruby/pull/4)
|
444
|
-
1. [Released in 1.0.2](https://github.com/abachman/ulid-ruby/compare/v1.0.0...v1.0.2)
|
445
|
-
|
446
|
-
### Compare performance with them
|
447
|
-
|
448
|
-
See [Benchmark](https://github.com/kachick/ruby-ulid/wiki/Benchmark).
|
401
|
+
## Migration from other gems
|
449
402
|
|
450
|
-
|
403
|
+
See [wiki page for gem migration](https://github.com/kachick/ruby-ulid/wiki/Gem-migration).
|
451
404
|
|
452
|
-
##
|
405
|
+
## RBS
|
453
406
|
|
454
|
-
|
407
|
+
Try at [examples/rbs_sandbox](https://github.com/kachick/ruby-ulid/tree/main/examples/rbs_sandbox).
|
455
408
|
|
456
409
|
I have checked the behavior with [ruby/rbs@2.6.0](https://github.com/ruby/rbs) + [soutaro/steep@1.0.1](https://github.com/soutaro/steep) + [soutaro/steep-vscode](https://github.com/soutaro/steep-vscode).
|
457
410
|
|
458
411
|
* ![rbs overview](./assets/ulid-rbs-overview.png?raw=true.png)
|
459
412
|
* ![rbs mix](./assets/ulid-rbs-mix.png?raw=true.png)
|
460
413
|
* ![rbs ng-to_str](./assets/ulid-rbs-ng-to_str.png?raw=true.png)
|
461
|
-
* ![rbs ok-at-time](./assets/ulid-rbs-ok-at-time.png?raw=true.png)
|
462
|
-
* ![rbs ng-at-int](./assets/ulid-rbs-ng-at-int.png?raw=true.png)
|
463
414
|
|
464
415
|
## References
|
465
416
|
|
data/lib/ulid/version.rb
CHANGED
data/lib/ulid.rb
CHANGED
@@ -268,6 +268,17 @@ class ULID
|
|
268
268
|
from_integer(CrockfordBase32.decode(string))
|
269
269
|
end
|
270
270
|
|
271
|
+
# @param [String, #to_str] string
|
272
|
+
# @return [ULID]
|
273
|
+
# @raise [ParserError] if the given format is not correct for ULID specs
|
274
|
+
def self.parse_variant_format(string)
|
275
|
+
string = String.try_convert(string)
|
276
|
+
raise(ArgumentError, 'ULID.parse_variant_format takes only strings') unless string
|
277
|
+
|
278
|
+
normalized_in_crockford = CrockfordBase32.normalize(string)
|
279
|
+
parse(normalized_in_crockford)
|
280
|
+
end
|
281
|
+
|
271
282
|
# @param [String, #to_str] string
|
272
283
|
# @return [String]
|
273
284
|
# @raise [ParserError] if the given format is not correct for ULID specs, even if ignored `orthographical variants of the format`
|
@@ -275,23 +286,40 @@ class ULID
|
|
275
286
|
string = String.try_convert(string)
|
276
287
|
raise(ArgumentError, 'ULID.normalize takes only strings') unless string
|
277
288
|
|
278
|
-
normalized_in_crockford = CrockfordBase32.normalize(string)
|
279
289
|
# Ensure the ULID correctness, because CrockfordBase32 does not always mean to satisfy ULID format
|
280
|
-
|
290
|
+
parse_variant_format(string).to_s
|
291
|
+
end
|
292
|
+
|
293
|
+
# @param [String, #to_str] string
|
294
|
+
# @return [Boolean]
|
295
|
+
def self.normalized?(string)
|
296
|
+
normalized = normalize(string)
|
297
|
+
rescue Exception
|
298
|
+
false
|
299
|
+
else
|
300
|
+
normalized == string
|
281
301
|
end
|
282
302
|
|
303
|
+
# @param [String, #to_str] string
|
283
304
|
# @return [Boolean]
|
284
|
-
def self.
|
285
|
-
|
305
|
+
def self.valid_as_variant_format?(string)
|
306
|
+
normalize(string)
|
286
307
|
rescue Exception
|
287
308
|
false
|
288
309
|
else
|
289
|
-
|
310
|
+
true
|
290
311
|
end
|
291
312
|
|
313
|
+
# @deprecated Use [.valid_as_variant_format?] or [.normalized?] instead
|
314
|
+
#
|
315
|
+
# Returns `true` if it is normalized string.
|
316
|
+
# Basically the difference of normalized? is to accept downcase or not. This returns true for downcased ULIDs.
|
317
|
+
#
|
292
318
|
# @return [Boolean]
|
293
|
-
def self.valid?(
|
294
|
-
|
319
|
+
def self.valid?(string)
|
320
|
+
warn_kwargs = (RUBY_VERSION >= '3.0') ? { category: :deprecated } : {}
|
321
|
+
Warning.warn('ULID.valid? is deprecated. Use ULID.valid_as_variant_format? or ULID.normalized? instead.', **warn_kwargs)
|
322
|
+
string = String.try_convert(string)
|
295
323
|
string ? STRICT_PATTERN_WITH_CROCKFORD_BASE32_SUBSET.match?(string) : false
|
296
324
|
end
|
297
325
|
|
@@ -392,7 +420,7 @@ class ULID
|
|
392
420
|
[ULID, @integer].hash
|
393
421
|
end
|
394
422
|
|
395
|
-
# @return [
|
423
|
+
# @return [-1, 0, 1, nil]
|
396
424
|
def <=>(other)
|
397
425
|
(ULID === other) ? (@integer <=> other.to_i) : nil
|
398
426
|
end
|
data/sig/ulid.rbs
CHANGED
@@ -213,6 +213,21 @@ class ULID < Object
|
|
213
213
|
# ```
|
214
214
|
def self.parse: (_ToStr string) -> ULID
|
215
215
|
|
216
|
+
# Get ULID instance from unnormalized String that encoded in Crockford's base32.
|
217
|
+
#
|
218
|
+
# http://www.crockford.com/base32.html
|
219
|
+
#
|
220
|
+
# * Ignore Hyphens (-)
|
221
|
+
# * Mapping 0 O o => 0, 1 I i L l => 1
|
222
|
+
#
|
223
|
+
# ```ruby
|
224
|
+
# ulid = ULID.parse_variant_format('01G70Y0Y7G-ZLXWDIREXERGSDoD')
|
225
|
+
# #=> ULID(2022-07-03 02:25:22.672 UTC: 01G70Y0Y7GZ1XWD1REXERGSD0D)
|
226
|
+
# ```
|
227
|
+
#
|
228
|
+
# See also [ulid/spec#57](https://github.com/ulid/spec/pull/57) and [ulid/spec#3](https://github.com/ulid/spec/issues/3)
|
229
|
+
def self.parse_variant_format: (_ToStr string) -> ULID
|
230
|
+
|
216
231
|
# ```ruby
|
217
232
|
# # Currently experimental feature, so needed to load the extension.
|
218
233
|
# require 'ulid/uuid'
|
@@ -309,14 +324,13 @@ class ULID < Object
|
|
309
324
|
# ```
|
310
325
|
def self.sample: (?period: period) -> ULID
|
311
326
|
| (Integer number, ?period: period?) -> Array[ULID]
|
312
|
-
def self.valid?: (untyped) -> bool
|
313
327
|
|
314
328
|
# Returns normalized string
|
315
329
|
#
|
316
330
|
# ```ruby
|
331
|
+
# ULID.normalize('01G70Y0Y7G-Z1XWDAREXERGSDDD') #=> "01G70Y0Y7GZ1XWDAREXERGSDDD"
|
317
332
|
# ULID.normalize('-olarz3-noekisv4rrff-q6ig5fav--') #=> "01ARZ3N0EK1SV4RRFFQ61G5FAV"
|
318
|
-
# ULID.
|
319
|
-
# ULID.normalized?('01ARZ3N0EK1SV4RRFFQ61G5FAV') #=> true
|
333
|
+
# ULID.normalize('01G70Y0Y7G_Z1XWDAREXERGSDDD') #=> ULID::ParserError
|
320
334
|
# ```
|
321
335
|
#
|
322
336
|
# See also [ulid/spec#57](https://github.com/ulid/spec/pull/57) and [ulid/spec#3](https://github.com/ulid/spec/issues/3)
|
@@ -325,13 +339,40 @@ class ULID < Object
|
|
325
339
|
# Returns `true` if it is normalized string
|
326
340
|
#
|
327
341
|
# ```ruby
|
328
|
-
# ULID.
|
329
|
-
# ULID.normalized?('-
|
330
|
-
# ULID.normalized?(
|
342
|
+
# ULID.normalized?('01G70Y0Y7GZ1XWDAREXERGSDDD') #=> true
|
343
|
+
# ULID.normalized?('01G70Y0Y7G-Z1XWDAREXERGSDDD') #=> false
|
344
|
+
# ULID.normalized?(ULID.generate.to_s.downcase) #=> false
|
345
|
+
# ULID.normalized?('01G70Y0Y7G_Z1XWDAREXERGSDDD') #=> false (Not raising ULID::ParserError)
|
331
346
|
# ```
|
332
347
|
#
|
333
348
|
# See also [ulid/spec#57](https://github.com/ulid/spec/pull/57) and [ulid/spec#3](https://github.com/ulid/spec/issues/3)
|
334
|
-
def self.normalized?: (
|
349
|
+
def self.normalized?: (_ToStr string) -> bool
|
350
|
+
| (untyped) -> false
|
351
|
+
|
352
|
+
# Returns `true` if it is valid in ULID format variants
|
353
|
+
#
|
354
|
+
# ```ruby
|
355
|
+
# ULID.valid_as_variant_format?(ULID.generate.to_s.downcase) #=> true
|
356
|
+
# ULID.valid_as_variant_format?('01G70Y0Y7G-Z1XWDAREXERGSDDD') #=> true
|
357
|
+
# ULID.valid_as_variant_format?('01G70Y0Y7G_Z1XWDAREXERGSDDD') #=> false
|
358
|
+
# ```
|
359
|
+
#
|
360
|
+
# See also [ulid/spec#57](https://github.com/ulid/spec/pull/57) and [ulid/spec#3](https://github.com/ulid/spec/issues/3)
|
361
|
+
def self.valid_as_variant_format?: (_ToStr string) -> bool
|
362
|
+
| (untyped) -> false
|
363
|
+
|
364
|
+
# DEPRECATED Use valid_as_variant_format? instead
|
365
|
+
#
|
366
|
+
# Returns `true` if it is normalized string.
|
367
|
+
# Basically the difference of normalized? is to accept downcase or not. This returns true for downcased ULIDs.
|
368
|
+
#
|
369
|
+
# ```ruby
|
370
|
+
# ULID.valid?(ULID.generate.to_s.downcase) #=> true
|
371
|
+
# ```
|
372
|
+
#
|
373
|
+
# See also [ulid/spec#57](https://github.com/ulid/spec/pull/57) and [ulid/spec#3](https://github.com/ulid/spec/issues/3)
|
374
|
+
def self.valid?: (_ToStr string) -> bool
|
375
|
+
| (untyped) -> false
|
335
376
|
|
336
377
|
# Returns parsed ULIDs from given String for rough operations.
|
337
378
|
#
|
@@ -411,7 +452,12 @@ class ULID < Object
|
|
411
452
|
# #=> true
|
412
453
|
# ```
|
413
454
|
#
|
414
|
-
# To be precise, this sorting unaffected with `case sensitive or not` and might handle [ulid/spec#57](https://github.com/ulid/spec/pull/57) in future.
|
455
|
+
# To be precise, this sorting unaffected with `case sensitive or not` and might handle [ulid/spec#57](https://github.com/ulid/spec/pull/57) in future.
|
456
|
+
# So preferable than `lexicographically sortable` in actual case.
|
457
|
+
#
|
458
|
+
# This returns -1 | 0 | 1 for ULIDs. However defined as returning Integer. It is caused on ruby/rbs current definition.
|
459
|
+
# https://github.com/ruby/ruby/blob/cd34f56d450f2310cceaf4c5f34d23eddfda58e8/numeric.c#L4646-L4660
|
460
|
+
# https://github.com/ruby/rbs/blob/14abbbae8885a09a2ed82de2ef31d67a9c0a108d/core/integer.rbs#L461-L462
|
415
461
|
#
|
416
462
|
def <=>: (ULID other) -> Integer
|
417
463
|
| (untyped other) -> nil
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-ulid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenichi Kamiya
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-07-
|
11
|
+
date: 2022-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: " generator,
|
14
|
-
|
13
|
+
description: " generator, optional monotonicity, parser and tools for ULID (RBS
|
14
|
+
included)\n"
|
15
15
|
email:
|
16
16
|
- kachick1+ruby@gmail.com
|
17
17
|
executables: []
|