cool_id 0.1.1 → 0.1.3
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/lib/cool_id/version.rb +1 -1
- data/lib/cool_id.rb +75 -43
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a61d8d06c3414dcec52ecd9a3f28696d0fafb683b2b206e025c33a1deb03de9
|
4
|
+
data.tar.gz: bc13a903ed6d5239eae6ee216f5da45699a525d755e914f9f9c2b81b6e33d26c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77aac33c12253962d7beabffc5d7101379f40d991b580c67ea0a306cd82f8d2befda21b23fbd3c3735a516863ef4c3565b18084f67ed001172b7a395527f3f4a
|
7
|
+
data.tar.gz: d3c269343bd10098fdd902424c10c22e676a0cea67d5dff404628863ea4d085319017b31d6c602364da024d36c30a470e1bd3ade7b687379bbbd3f011a72191c
|
data/lib/cool_id/version.rb
CHANGED
data/lib/cool_id.rb
CHANGED
@@ -3,76 +3,90 @@
|
|
3
3
|
require_relative "cool_id/version"
|
4
4
|
require "nanoid"
|
5
5
|
require "active_support/concern"
|
6
|
-
require "active_record"
|
7
6
|
|
8
7
|
module CoolId
|
9
8
|
class Error < StandardError; end
|
10
9
|
|
10
|
+
# defaults based on https://planetscale.com/blog/why-we-chose-nanoids-for-planetscales-api
|
11
|
+
DEFAULT_SEPARATOR = "_"
|
12
|
+
DEFAULT_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz"
|
13
|
+
DEFAULT_LENGTH = 12
|
14
|
+
|
15
|
+
Id = Struct.new(:key, :prefix, :id, :model_class)
|
16
|
+
|
11
17
|
class << self
|
12
|
-
attr_accessor :separator
|
18
|
+
attr_accessor :separator, :alphabet, :length
|
13
19
|
|
14
20
|
def configure
|
15
21
|
yield self
|
16
22
|
end
|
17
23
|
|
24
|
+
def reset_configuration
|
25
|
+
self.separator = DEFAULT_SEPARATOR
|
26
|
+
self.alphabet = DEFAULT_ALPHABET
|
27
|
+
self.length = DEFAULT_LENGTH
|
28
|
+
end
|
29
|
+
|
18
30
|
def registry
|
19
|
-
@
|
31
|
+
@prefix_map ||= Registry.new
|
20
32
|
end
|
21
33
|
|
22
34
|
def generate_id(config)
|
23
|
-
|
24
|
-
|
35
|
+
alphabet = config.alphabet || @alphabet
|
36
|
+
length = config.length || @length
|
37
|
+
id = Nanoid.generate(size: length, alphabet: alphabet)
|
38
|
+
|
39
|
+
"#{config.prefix}#{separator}#{id}"
|
25
40
|
end
|
26
41
|
end
|
27
42
|
|
28
|
-
self.separator =
|
43
|
+
self.separator = DEFAULT_SEPARATOR
|
44
|
+
self.alphabet = DEFAULT_ALPHABET
|
45
|
+
self.length = DEFAULT_LENGTH
|
29
46
|
|
30
47
|
class Registry
|
31
48
|
def initialize
|
32
|
-
@
|
49
|
+
@prefix_map = {}
|
33
50
|
end
|
34
51
|
|
35
52
|
def register(prefix, model_class)
|
36
|
-
@
|
53
|
+
@prefix_map[prefix] = model_class
|
37
54
|
end
|
38
55
|
|
39
|
-
def
|
40
|
-
|
56
|
+
def locate(id)
|
57
|
+
parsed = parse(id)
|
58
|
+
parsed&.model_class&.find_by(id: id)
|
41
59
|
end
|
42
60
|
|
43
|
-
def
|
44
|
-
prefix,
|
45
|
-
model_class =
|
46
|
-
model_class
|
47
|
-
|
48
|
-
|
49
|
-
def find_record!(id)
|
50
|
-
prefix, _ = id.split(CoolId.separator, 2)
|
51
|
-
model_class = find_model(prefix)
|
52
|
-
model_class&.find(id)
|
61
|
+
def parse(id)
|
62
|
+
prefix, key = id.split(CoolId.separator, 2)
|
63
|
+
model_class = @prefix_map[prefix]
|
64
|
+
return nil unless model_class
|
65
|
+
Id.new(key, prefix, id, model_class)
|
53
66
|
end
|
54
67
|
end
|
55
68
|
|
56
69
|
class Config
|
57
70
|
attr_reader :prefix, :length, :alphabet
|
58
71
|
|
59
|
-
def initialize(prefix
|
60
|
-
@prefix = prefix
|
72
|
+
def initialize(prefix:, length: nil, alphabet: nil)
|
61
73
|
@length = length
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
def alphabet=(value)
|
66
|
-
validate_alphabet(value)
|
67
|
-
@alphabet = value
|
74
|
+
@prefix = validate_prefix(prefix)
|
75
|
+
@alphabet = validate_alphabet(alphabet)
|
68
76
|
end
|
69
77
|
|
70
78
|
private
|
71
79
|
|
80
|
+
def validate_prefix(value)
|
81
|
+
raise ArgumentError, "Prefix cannot be nil" if value.nil?
|
82
|
+
raise ArgumentError, "Prefix cannot be empty" if value.empty?
|
83
|
+
value
|
84
|
+
end
|
85
|
+
|
72
86
|
def validate_alphabet(value)
|
73
|
-
if value.
|
74
|
-
|
75
|
-
|
87
|
+
return nil if value.nil?
|
88
|
+
raise ArgumentError, "Alphabet cannot include the separator '#{CoolId.separator}'" if value.include?(CoolId.separator)
|
89
|
+
value
|
76
90
|
end
|
77
91
|
end
|
78
92
|
|
@@ -80,39 +94,57 @@ module CoolId
|
|
80
94
|
extend ActiveSupport::Concern
|
81
95
|
|
82
96
|
class_methods do
|
83
|
-
|
84
|
-
|
85
|
-
def cool_id(options = {})
|
86
|
-
register_cool_id(options)
|
87
|
-
end
|
97
|
+
attr_accessor :cool_id_config
|
98
|
+
attr_accessor :cool_id_setup_required
|
88
99
|
|
89
|
-
def
|
90
|
-
raise ArgumentError, "Prefix cannot be empty" if options[:prefix] && options[:prefix].empty?
|
100
|
+
def cool_id(options)
|
91
101
|
@cool_id_config = Config.new(**options)
|
92
102
|
CoolId.registry.register(options[:prefix], self)
|
93
103
|
end
|
94
104
|
|
95
105
|
def generate_cool_id
|
96
|
-
CoolId.generate_id(@cool_id_config
|
106
|
+
CoolId.generate_id(@cool_id_config)
|
107
|
+
end
|
108
|
+
|
109
|
+
def ensure_cool_id_setup
|
110
|
+
@cool_id_setup_required = true
|
111
|
+
end
|
112
|
+
|
113
|
+
def skip_cool_id_setup
|
114
|
+
@cool_id_setup_required = false
|
115
|
+
end
|
116
|
+
|
117
|
+
def inherited(subclass)
|
118
|
+
super
|
119
|
+
if @cool_id_setup_required && !subclass.instance_variable_defined?(:@cool_id_setup_required)
|
120
|
+
subclass.instance_variable_set(:@cool_id_setup_required, true)
|
121
|
+
end
|
97
122
|
end
|
98
123
|
end
|
99
124
|
|
100
125
|
included do
|
101
126
|
before_create :set_cool_id
|
127
|
+
after_initialize :ensure_cool_id_configured
|
102
128
|
|
103
129
|
private
|
104
130
|
|
105
131
|
def set_cool_id
|
106
132
|
self.id = self.class.generate_cool_id if id.blank?
|
107
133
|
end
|
134
|
+
|
135
|
+
def ensure_cool_id_configured
|
136
|
+
if self.class.cool_id_setup_required && self.class.cool_id_config.nil?
|
137
|
+
raise Error, "CoolId not configured for #{self.class}. Use 'cool_id' to configure or 'skip_cool_id_setup' to opt out."
|
138
|
+
end
|
139
|
+
end
|
108
140
|
end
|
109
141
|
end
|
110
142
|
|
111
|
-
def self.
|
112
|
-
registry.
|
143
|
+
def self.locate(id)
|
144
|
+
registry.locate(id)
|
113
145
|
end
|
114
146
|
|
115
|
-
def self.
|
116
|
-
registry.
|
147
|
+
def self.parse(id)
|
148
|
+
registry.parse(id)
|
117
149
|
end
|
118
150
|
end
|
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.3
|
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-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nanoid
|