cool_id 0.1.7 → 0.1.9
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.
- checksums.yaml +4 -4
- data/.aider.conf.yml +9 -0
- data/README.md +17 -0
- data/lib/cool_id/version.rb +1 -1
- data/lib/cool_id.rb +40 -10
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07011e094fb16385d448b80b4461b0e579d29efc0b4273fff4b41dd1df350a64
|
4
|
+
data.tar.gz: 11d8a83f95a7fce11598df98d1b7175c26b00f8a0d19d6af18ebaa35b8ddfa0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f98ab9a494119599b383cc41bc9fdb797f68e793f626b07759899fee06ded282b6b8fe4f98d8ab82425127c64f4daac2511b8645f61458625e8356c8a428efe0
|
7
|
+
data.tar.gz: 6002ff50f083a330ad2fcdb582df9e12d9aea31d26e1d7f737dcd20650c0fa7454e2eb43a7f88c84e47bcdb5f9965557433d97acfca13b0afa854032c4de28fa
|
data/.aider.conf.yml
ADDED
data/README.md
CHANGED
@@ -35,9 +35,26 @@ and generate ids without creating a record
|
|
35
35
|
# generate an id, e.g. for batch inserts or upserts
|
36
36
|
User.generate_cool_id
|
37
37
|
# => "usr_vktd1b5v84lr"
|
38
|
+
```
|
39
|
+
|
40
|
+
you can use cool_id with a separate field, keeping the default primary key:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class Product < ActiveRecord::Base
|
44
|
+
include CoolId::Model
|
45
|
+
cool_id prefix: "prd", id_field: :public_id
|
46
|
+
end
|
38
47
|
|
48
|
+
product = Product.create!(name: "Cool Product")
|
49
|
+
product.id # => 1 (or another integer)
|
50
|
+
product.public_id # => "prd_vktd1b5v84lr"
|
51
|
+
|
52
|
+
# You can still use CoolId.locate with the public_id
|
53
|
+
CoolId.locate("prd_vktd1b5v84lr") # => #<Product id: 1, public_id: "prd_vktd1b5v84lr", name: "Cool Product">
|
39
54
|
```
|
40
55
|
|
56
|
+
this approach allows you to keep your primary key as an auto-incrementing integer while still benefiting from CoolId's functionality. it's particularly useful when you want to expose a public identifier that's separate from your internal primary key.
|
57
|
+
|
41
58
|
it takes parameters to change the alphabet or length
|
42
59
|
|
43
60
|
```ruby
|
data/lib/cool_id/version.rb
CHANGED
data/lib/cool_id.rb
CHANGED
@@ -7,15 +7,18 @@ require "active_support/concern"
|
|
7
7
|
module CoolId
|
8
8
|
class NotConfiguredError < StandardError; end
|
9
9
|
|
10
|
+
class MaxRetriesExceededError < StandardError; end
|
11
|
+
|
10
12
|
# defaults based on https://planetscale.com/blog/why-we-chose-nanoids-for-planetscales-api
|
11
13
|
DEFAULT_SEPARATOR = "_"
|
12
14
|
DEFAULT_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz"
|
13
15
|
DEFAULT_LENGTH = 12
|
16
|
+
DEFAULT_MAX_RETRIES = 1000
|
14
17
|
|
15
|
-
Id = Struct.new(:key, :prefix, :id, :model_class)
|
18
|
+
Id = Struct.new(:key, :prefix, :id, :model_class, :id_field)
|
16
19
|
|
17
20
|
class << self
|
18
|
-
attr_accessor :separator, :alphabet, :length
|
21
|
+
attr_accessor :separator, :alphabet, :length, :max_retries, :id_field
|
19
22
|
|
20
23
|
def configure
|
21
24
|
yield self
|
@@ -25,6 +28,8 @@ module CoolId
|
|
25
28
|
self.separator = DEFAULT_SEPARATOR
|
26
29
|
self.alphabet = DEFAULT_ALPHABET
|
27
30
|
self.length = DEFAULT_LENGTH
|
31
|
+
self.max_retries = DEFAULT_MAX_RETRIES
|
32
|
+
self.id_field = nil
|
28
33
|
end
|
29
34
|
|
30
35
|
def registry
|
@@ -34,15 +39,32 @@ module CoolId
|
|
34
39
|
def generate_id(config)
|
35
40
|
alphabet = config.alphabet || @alphabet
|
36
41
|
length = config.length || @length
|
37
|
-
|
42
|
+
max_retries = config.max_retries || @max_retries
|
43
|
+
|
44
|
+
retries = 0
|
45
|
+
loop do
|
46
|
+
nano_id = Nanoid.generate(size: length, alphabet: alphabet)
|
47
|
+
full_id = "#{config.prefix}#{separator}#{nano_id}"
|
48
|
+
if !config.model_class.exists?(id: full_id)
|
49
|
+
return full_id
|
50
|
+
end
|
38
51
|
|
39
|
-
|
52
|
+
retries += 1
|
53
|
+
if retries >= max_retries
|
54
|
+
raise MaxRetriesExceededError, "Failed to generate a unique ID after #{max_retries} attempts"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def resolve_cool_id_field(model_class)
|
60
|
+
model_class.cool_id_config&.id_field || CoolId.id_field || model_class.primary_key
|
40
61
|
end
|
41
62
|
end
|
42
63
|
|
43
64
|
self.separator = DEFAULT_SEPARATOR
|
44
65
|
self.alphabet = DEFAULT_ALPHABET
|
45
66
|
self.length = DEFAULT_LENGTH
|
67
|
+
self.max_retries = DEFAULT_MAX_RETRIES
|
46
68
|
|
47
69
|
class Registry
|
48
70
|
def initialize
|
@@ -55,24 +77,31 @@ module CoolId
|
|
55
77
|
|
56
78
|
def locate(id)
|
57
79
|
parsed = parse(id)
|
58
|
-
parsed
|
80
|
+
return nil unless parsed
|
81
|
+
|
82
|
+
id_field = CoolId.resolve_cool_id_field(parsed.model_class)
|
83
|
+
parsed.model_class.find_by(id_field => id)
|
59
84
|
end
|
60
85
|
|
61
86
|
def parse(id)
|
62
87
|
prefix, key = id.split(CoolId.separator, 2)
|
63
88
|
model_class = @prefix_map[prefix]
|
64
89
|
return nil unless model_class
|
65
|
-
|
90
|
+
id_field = CoolId.resolve_cool_id_field(model_class)
|
91
|
+
Id.new(key, prefix, id, model_class, id_field)
|
66
92
|
end
|
67
93
|
end
|
68
94
|
|
69
95
|
class Config
|
70
|
-
attr_reader :prefix, :length, :alphabet
|
96
|
+
attr_reader :prefix, :length, :alphabet, :max_retries, :model_class, :id_field
|
71
97
|
|
72
|
-
def initialize(prefix:, length: nil, alphabet: nil)
|
98
|
+
def initialize(prefix:, model_class:, length: nil, alphabet: nil, max_retries: nil, id_field: nil)
|
73
99
|
@length = length
|
74
100
|
@prefix = validate_prefix(prefix)
|
75
101
|
@alphabet = validate_alphabet(alphabet)
|
102
|
+
@max_retries = max_retries
|
103
|
+
@model_class = model_class
|
104
|
+
@id_field = id_field
|
76
105
|
end
|
77
106
|
|
78
107
|
private
|
@@ -98,7 +127,7 @@ module CoolId
|
|
98
127
|
attr_accessor :cool_id_setup_required
|
99
128
|
|
100
129
|
def cool_id(options)
|
101
|
-
@cool_id_config = Config.new(**options)
|
130
|
+
@cool_id_config = Config.new(**options, model_class: self)
|
102
131
|
CoolId.registry.register(options[:prefix], self)
|
103
132
|
end
|
104
133
|
|
@@ -129,7 +158,8 @@ module CoolId
|
|
129
158
|
private
|
130
159
|
|
131
160
|
def set_cool_id
|
132
|
-
|
161
|
+
id_field = CoolId.resolve_cool_id_field(self.class)
|
162
|
+
self[id_field] = self.class.generate_cool_id if self[id_field].blank?
|
133
163
|
end
|
134
164
|
|
135
165
|
def ensure_cool_id_configured
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cool_id
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Schilling
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-08-
|
11
|
+
date: 2024-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nanoid
|
@@ -73,6 +73,7 @@ executables: []
|
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
|
+
- ".aider.conf.yml"
|
76
77
|
- ".rspec"
|
77
78
|
- ".standard.yml"
|
78
79
|
- CHANGELOG.md
|