badged_ids 1.0.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +219 -0
- data/Rakefile +11 -0
- data/lib/badged_ids/badged_id.rb +44 -0
- data/lib/badged_ids/configuration.rb +66 -0
- data/lib/badged_ids/errors.rb +5 -0
- data/lib/badged_ids/rails.rb +47 -0
- data/lib/badged_ids/railtie.rb +9 -0
- data/lib/badged_ids/registry.rb +29 -0
- data/lib/badged_ids/version.rb +3 -0
- data/lib/badged_ids.rb +33 -0
- metadata +73 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4d4e44d20b4fe1ff726d0311f0d9d528d4622c8fa1e0bdd4397bdaf217b43a94
|
4
|
+
data.tar.gz: b53e26dad7bb2cd5e822c7df83ea837e6cc2ce28368fefb66160ac395d3bf291
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e2c1b8beca316c503319691e34cdbb60f1751ed2eec83eefe552b26c9a317cfe9c4ad60cb94a8d45d5d966df34ef4966e9316236b6f149d9e5ad780db93d83cb
|
7
|
+
data.tar.gz: 5b56ff1d8efb74cb2cdc9e132a0eb36be059553fa3d5410bfd0a80893d4c4f1f63e7def719ea4382a0657db6fdee6f26b860cfc32c98f1b11384bf7c62104443
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright Fabian Schwarz
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
# Badged IDs
|
2
|
+
|
3
|
+
### Descriptive and Secure IDs for your Rails Models
|
4
|
+
[](https://github.com/fabian12943/badged_ids/actions)
|
5
|
+
|
6
|
+
Badged IDs makes it simple to create descriptive and secure identifiers for your Rails
|
7
|
+
models.
|
8
|
+
|
9
|
+
By combining a badge with a randomly generated string, it helps you to prevent
|
10
|
+
[vulnerabilities associated with sequential IDs]() while keeping your IDs relatively short (e.g. compared to
|
11
|
+
[UUIDs](https://developer.mozilla.org/en-US/docs/Glossary/UUID)). Additionally,
|
12
|
+
it allows you to clearly identify the type of record, even when the ID is seen out of context,
|
13
|
+
enhancing both readability and traceability.
|
14
|
+
|
15
|
+
#### Example:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
Order.create(/* ... */).id
|
19
|
+
# => "ord_24t6pjz7wpecix5"
|
20
|
+
|
21
|
+
Order.find("ord_24t6pjz7wpecix5")
|
22
|
+
# => #<Order id: "ord_24t6pjz7wpecix5", ...>
|
23
|
+
|
24
|
+
BadgedIds.find("ord_24t6pjz7wpecix5")
|
25
|
+
# => #<Order id: "ord_24t6pjz7wpecix5", ...>
|
26
|
+
```
|
27
|
+
|
28
|
+
The ID generation is highly configurable, enabling you to customize the badge, delimiter, length,
|
29
|
+
character set, and much more to suit your application’s needs.
|
30
|
+
|
31
|
+
Inspired by [Stripe's prefixed IDs](https://stripe.com/docs/api) and [Chris Oliver's prefixed_ids
|
32
|
+
gem](https://github.com/excid3/prefixed_ids).
|
33
|
+
|
34
|
+
## Installation
|
35
|
+
|
36
|
+
1. Add the following line to your app's `Gemfile`:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
gem 'badged_ids'
|
40
|
+
```
|
41
|
+
2. Run the following command to install it:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
$ bundle install
|
45
|
+
```
|
46
|
+
|
47
|
+
## Usage
|
48
|
+
|
49
|
+
### Prerequisites
|
50
|
+
|
51
|
+
Ensure that the primary key of your model (typically `id`), or the field where you intend to store
|
52
|
+
the badged ID, is of type string.
|
53
|
+
|
54
|
+
To set the primary key for a new table to a string, you can use the following migration:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
create_table :orders, id: :string do |t|
|
58
|
+
# Add your columns here
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
If you like the generator to use string primary keys by default, add this to your `config/application.rb`:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
# config/application.rb
|
66
|
+
config.generators do |g|
|
67
|
+
g.orm :active_record, primary_key_type: :string
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
### Basic Usage
|
72
|
+
|
73
|
+
To enable Badged IDs for your model, simplfy include the `has_badged_id` method and specify a badge
|
74
|
+
for your model. The badge is a short prefix that helps you to quickly identify the type of a record.
|
75
|
+
|
76
|
+
That's it! Now, whenever you create a new record, a unique Badged ID is automatically generated and
|
77
|
+
assigned to the primary key column of the record.
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
class Order < ApplicationRecord
|
81
|
+
has_badged_id :ord
|
82
|
+
end
|
83
|
+
|
84
|
+
Order.create(/* ... */).id
|
85
|
+
# => "ord_24t6pjz7wpecix5"
|
86
|
+
```
|
87
|
+
|
88
|
+
> [!NOTE]
|
89
|
+
> This basic setup uses the default configuration settings, but you can customize them
|
90
|
+
> *globally* or *per-model* to better suit your application's needs. For more information on configuring
|
91
|
+
> Badged IDs, refer to the [Configuration](#configuration) section.
|
92
|
+
|
93
|
+
### Find any record by Badged ID
|
94
|
+
|
95
|
+
You can easily find any record by its Badged ID using `BadgedIds.find`. Just provide the full badged ID (including the badge) to retrieve the corresponding record.
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
BadgedIds.find("ord_24t6pjz7wpecix5")
|
99
|
+
# => #<Order id: "ord_24t6pjz7wpecix5", ...>
|
100
|
+
|
101
|
+
BadgedIds.find("usr_y0m4ud4iy94sq2y")
|
102
|
+
# => #<User id: "usr_y0m4ud4iy94sq2y", ...>
|
103
|
+
```
|
104
|
+
|
105
|
+
### Manually generate Badged IDs for a model
|
106
|
+
|
107
|
+
If you need to generate Badged IDs manually—such as when performing batch inserts or processing
|
108
|
+
records in bulk—you can use the `generate_badged_id` method.
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
Order.generate_badged_id
|
112
|
+
# => "ord_24t6pjz7wpecix5"
|
113
|
+
```
|
114
|
+
|
115
|
+
## Configuration
|
116
|
+
|
117
|
+
### Global Configuration
|
118
|
+
|
119
|
+
Various configuration options are available to adjust the behavior to your application's needs.
|
120
|
+
You can define global settings by creating or modifying the `config/initializers/badged_ids.rb` file
|
121
|
+
in your Rails application.
|
122
|
+
|
123
|
+
#### Example
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
# config/initializers/badged_ids.rb
|
127
|
+
BadgedIds.configure do |config|
|
128
|
+
config.alphabet = "abc123"
|
129
|
+
config.delimiter = "-"
|
130
|
+
config.minimum_length = 20
|
131
|
+
config.max_generation_attempts = 3
|
132
|
+
config.skip_uniqueness_check = false
|
133
|
+
config.implicit_order_column = :created_at
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
#### Available Configuration Options
|
138
|
+
|
139
|
+
The table below details all available configuration options and their default values:
|
140
|
+
|
141
|
+
| Config | Description | Default |
|
142
|
+
| ------------------------ | ----------------------------------------------------------------------------- | ---------------------------------------- |
|
143
|
+
| alphabet | Characters used to generate the random part of the ID. | `"abcdefghijklmnopqrstuvwxyz0123456789"` |
|
144
|
+
| delimiter | String separating the badge from the random string in the ID. | `"_"` |
|
145
|
+
| minimum_length | Length of the random part of the ID, excluding the badge and delimiter. | `15` |
|
146
|
+
| max_generation_attemptsÂą | Maximum attempts to generate a unique ID before raising an error. | `1` |
|
147
|
+
| skip_uniqueness_check² | Skip uniqueness check and retry mechanism when generating a new ID. | `false` |
|
148
|
+
| implicit_order_column | Default column used for ordering records of model, if not explicitly defined. | `nil` |
|
149
|
+
|
150
|
+
Âą It is recommended to leave this value as-is. If you encounter collisions, it's likely that the
|
151
|
+
`minimum_length` is too short and/or the `alphabet` contains too few unique characters.
|
152
|
+
When configured properly, the chances of a collision are virtually zero.
|
153
|
+
If you're uncertain, it's best to stick with the default values.
|
154
|
+
|
155
|
+
² You can skip the uniqueness check if you're confident that the combination of `minimum_length`
|
156
|
+
and `alphabet` ensures that collisions are virtually impossible. This improves performance when creating thousands
|
157
|
+
of records at once (see [Benchmarks](#benchmarks)).
|
158
|
+
|
159
|
+
### Model Overrides
|
160
|
+
|
161
|
+
When defining a model with `has_badged_id`, you can override specific settings for that model. These
|
162
|
+
options allow you to fine-tune the ID generation without affecting the global configuration.
|
163
|
+
|
164
|
+
#### Example
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
class Order < ApplicationRecord
|
168
|
+
has_badged_id :ord, id_field: :public_id, alphabet: "ABCDEF0123456789", minimum_length: 20
|
169
|
+
end
|
170
|
+
|
171
|
+
Order.create(/* ... */).public_id
|
172
|
+
# => "ord_E19D5E5ADB476416C1F6"
|
173
|
+
```
|
174
|
+
|
175
|
+
#### Available Model Overrides
|
176
|
+
|
177
|
+
The table below details all available options that can be overridden on a per-model basis and their default values:
|
178
|
+
|
179
|
+
| Option | Description | Default |
|
180
|
+
| ----------------------- | ----------------------------------------------------------------------------- | ---------------------------------- |
|
181
|
+
| id_field | Database field used for storing the ID. Must be of type `string`. | `model.primary_key` (usually `id`) |
|
182
|
+
| alphabet | Characters used to generate the random part of the ID. | `config.alphabet` |
|
183
|
+
| minimum_length | Length of the random part of the ID, excluding the badge and delimiter. | `config.minimum_length` |
|
184
|
+
| max_generation_attempts | Maximum attempts to generate a unique ID before raising an error. | `config.max_generation_attempts` |
|
185
|
+
| skip_uniqueness_check | Skip uniqueness check and retry mechanism when generating a new ID. | `config.skip_uniqueness_check` |
|
186
|
+
| implicit_order_column | Default column used for ordering records of model, if not explicitly defined. | `config.implicit_order_column` |
|
187
|
+
|
188
|
+
### Configuration Validation
|
189
|
+
|
190
|
+
Both global and model-specific configurations are validated at two critical points: during
|
191
|
+
application startup and immediately before generating a new ID. If any configuration is invalid,
|
192
|
+
an error is raised with a detailed message on how to resolve the issue.
|
193
|
+
|
194
|
+
## Benchmarks
|
195
|
+
|
196
|
+
The following benchmarks compare the performance of Badged IDs with other common ID generation
|
197
|
+
methods when creating 20,000 simple records on my local machine.
|
198
|
+
|
199
|
+
| | user | system | total | real |
|
200
|
+
| --------------------------------------------- | --------- | -------- | --------- | --------- |
|
201
|
+
| Sequential integer id | 15.266384 | 1.211182 | 16.477566 | 21.128873 |
|
202
|
+
| UUIDv4 | 15.324471 | 1.315743 | 16.640214 | 21.262059 |
|
203
|
+
| Badged ID<br>(`skip_uniqueness_check: true`) | 15.898291 | 1.245899 | 17.144190 | 21.599303 |
|
204
|
+
| Badged ID<br>(`skip_uniqueness_check: false`) | 22.520556 | 1.696816 | 24.217372 | 30.400110 |
|
205
|
+
|
206
|
+
### Conclusion
|
207
|
+
|
208
|
+
When using Badged IDs with `skip_uniqueness_check: true`, the performance is slightly slower than
|
209
|
+
that of sequential integer IDs or UUIDs, but the difference is minimal. This configuration is ideal
|
210
|
+
when the `alphabet` and `minimum_length` ensure that collisions are virtually impossible.
|
211
|
+
|
212
|
+
When using Badged IDs with `skip_uniqueness_check: false`, the performance is notably slower
|
213
|
+
than that of sequential integer IDs or UUIDs. This configuration is only recommended when the risk
|
214
|
+
of collision is a realistic concern due to a short `alphabet` and/or `minimum_length` that, for
|
215
|
+
whatever reason, cannot be adjusted. In such cases, verifying the uniqueness of the generated ID
|
216
|
+
before saving and retrying in the event of a collision becomes necessary.
|
217
|
+
|
218
|
+
For most use cases, especially when not creating thousands of records at once,
|
219
|
+
the performance impact is negligible, regardless of the `skip_uniqueness_check` config.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module BadgedIds
|
2
|
+
class BadgedId
|
3
|
+
attr_reader :badge, :id_field, :config
|
4
|
+
|
5
|
+
def initialize(model, badge, options = {})
|
6
|
+
@badge = badge.to_s
|
7
|
+
@id_field = options.fetch(:id_field, model.primary_key).to_s
|
8
|
+
@config = build_config(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate_id
|
12
|
+
validate!
|
13
|
+
"#{badge}#{config.delimiter}#{generate_random_part}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate!
|
17
|
+
config.validate!
|
18
|
+
validate_badge_delimiter_combination
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def build_config(options)
|
25
|
+
BadgedIds.config.dup.tap do |config|
|
26
|
+
options.slice(*Configuration::OVERRIDABLE_CONFIGS_PER_MODEL).each do |key, value|
|
27
|
+
config.public_send("#{key}=", value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_random_part
|
33
|
+
SecureRandom.alphanumeric(config.minimum_length, chars: config.alphabet.chars)
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate_badge_delimiter_combination
|
37
|
+
overlapping_chars = badge.chars & config.delimiter.chars
|
38
|
+
return if overlapping_chars.empty?
|
39
|
+
|
40
|
+
formatted_chars = overlapping_chars.map { |char| "`#{char}`" }.join(", ")
|
41
|
+
raise ConfigError, "Badge and delimiter cannot share characters: #{formatted_chars}."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module BadgedIds
|
2
|
+
class Configuration
|
3
|
+
CONFIG_DEFAULTS = {
|
4
|
+
delimiter: "_",
|
5
|
+
alphabet: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
|
6
|
+
minimum_length: 24,
|
7
|
+
implicit_order_column: nil,
|
8
|
+
max_generation_attempts: 1,
|
9
|
+
skip_uniqueness_check: false
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
OVERRIDABLE_CONFIGS_PER_MODEL = CONFIG_DEFAULTS.keys - %i[delimiter]
|
13
|
+
|
14
|
+
attr_accessor(*CONFIG_DEFAULTS.keys)
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
CONFIG_DEFAULTS.each { |key, value| instance_variable_set("@#{key}", value) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate!
|
21
|
+
%i[
|
22
|
+
validate_delimiter
|
23
|
+
validate_alphabet
|
24
|
+
validate_alphabet_delimiter_combination
|
25
|
+
validate_minimum_length
|
26
|
+
validate_max_generation_attempts
|
27
|
+
].each { |method| send(method) }
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_h
|
32
|
+
CONFIG_DEFAULTS.keys.each_with_object({}) { |key, hash| hash[key] = public_send(key) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def reset_to_defaults!
|
36
|
+
CONFIG_DEFAULTS.each { |key, value| public_send("#{key}=", value) }
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def validate_delimiter
|
42
|
+
raise ConfigError, "Delimiter cannot be blank." if delimiter.to_s.strip.empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_alphabet
|
46
|
+
raise ConfigError, "Alphabet cannot be blank." if alphabet.to_s.strip.empty?
|
47
|
+
raise ConfigError, "Alphabet must contain at least two unique characters." if alphabet.chars.uniq.size < 2
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_alphabet_delimiter_combination
|
51
|
+
overlapping_chars = delimiter.chars & alphabet.chars
|
52
|
+
return if overlapping_chars.empty?
|
53
|
+
|
54
|
+
formatted_chars = overlapping_chars.map { |char| "`#{char}`" }.join(", ")
|
55
|
+
raise ConfigError, "Alphabet and delimiter cannot share characters: #{formatted_chars}."
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate_minimum_length
|
59
|
+
raise ConfigError, "Minimum length must be greater than 0." if minimum_length < 1
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate_max_generation_attempts
|
63
|
+
raise ConfigError, "Max generation attempts must be greater than 0." if max_generation_attempts < 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "badged_ids/badged_id"
|
2
|
+
|
3
|
+
module BadgedIds
|
4
|
+
module Rails
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :_badged_id
|
9
|
+
end
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
def has_badged_id(badge, **options)
|
13
|
+
self._badged_id = BadgedId.new(self, badge, **options)
|
14
|
+
Registry.register(badge, self)
|
15
|
+
|
16
|
+
before_create { self[_badged_id.id_field] ||= self.class.generate_badged_id }
|
17
|
+
|
18
|
+
if _badged_id.config.implicit_order_column.present? && implicit_order_column.nil?
|
19
|
+
self.implicit_order_column = _badged_id.config.implicit_order_column
|
20
|
+
end
|
21
|
+
|
22
|
+
define_singleton_method(:generate_badged_id) do
|
23
|
+
return _badged_id.generate_id if _badged_id.config.skip_uniqueness_check
|
24
|
+
|
25
|
+
generated_ids = Set.new
|
26
|
+
attempts = 0
|
27
|
+
|
28
|
+
loop do
|
29
|
+
generated_id = _badged_id.generate_id
|
30
|
+
|
31
|
+
unless generated_ids.include?(generated_id)
|
32
|
+
generated_ids.add(generated_id)
|
33
|
+
return generated_id unless exists?(id: generated_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
if (attempts += 1) >= _badged_id.config.max_generation_attempts
|
37
|
+
raise Error, <<~MESSAGE.squish
|
38
|
+
Failed to generate a unique badged ID within #{_badged_id.config.max_generation_attempts} attempts.
|
39
|
+
Consider increasing the minimum length or the unique characters in the alphabet.
|
40
|
+
MESSAGE
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module BadgedIds
|
2
|
+
class Registry
|
3
|
+
mattr_accessor :models, default: {}
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def register(badge, model)
|
7
|
+
badge = badge.to_s
|
8
|
+
if models.key?(badge) && models[badge] != model
|
9
|
+
raise RegistryError, "Badge `#{badge}` is already assigned to `#{models[badge]}`."
|
10
|
+
end
|
11
|
+
|
12
|
+
models[badge] = model
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_model(badge)
|
16
|
+
models.fetch(badge.to_s) do
|
17
|
+
raise RegistryError, <<~MESSAGE.squish
|
18
|
+
No model with the badge `#{badge}` registered.
|
19
|
+
Available badges are: #{registered_badges.join(", ")}.
|
20
|
+
MESSAGE
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def registered_badges
|
25
|
+
models.keys
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/badged_ids.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "badged_ids/version"
|
2
|
+
require "badged_ids/railtie"
|
3
|
+
require "badged_ids/errors"
|
4
|
+
require "badged_ids/registry"
|
5
|
+
require "badged_ids/rails"
|
6
|
+
require "badged_ids/configuration"
|
7
|
+
|
8
|
+
module BadgedIds
|
9
|
+
@config = Configuration.new
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def config
|
13
|
+
if block_given?
|
14
|
+
yield @config
|
15
|
+
@config.validate!
|
16
|
+
else
|
17
|
+
@config
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def find(badged_id)
|
22
|
+
badge, _id = split_id(badged_id)
|
23
|
+
Registry.find_model(badge).find(badged_id)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def split_id(badged_id, delimiter = config.delimiter)
|
29
|
+
badge, _, id = badged_id.to_s.rpartition(delimiter)
|
30
|
+
[ badge, id ]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: badged_ids
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Fabian Schwarz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-01-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 6.0.0
|
27
|
+
description: Badged-IDs generates and persists unguessable IDs with friendly prefixes
|
28
|
+
for your models
|
29
|
+
email:
|
30
|
+
- fabian12943@gmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- MIT-LICENSE
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- lib/badged_ids.rb
|
39
|
+
- lib/badged_ids/badged_id.rb
|
40
|
+
- lib/badged_ids/configuration.rb
|
41
|
+
- lib/badged_ids/errors.rb
|
42
|
+
- lib/badged_ids/rails.rb
|
43
|
+
- lib/badged_ids/railtie.rb
|
44
|
+
- lib/badged_ids/registry.rb
|
45
|
+
- lib/badged_ids/version.rb
|
46
|
+
homepage: https://github.com/fabian12943/badged_ids
|
47
|
+
licenses:
|
48
|
+
- MIT
|
49
|
+
metadata:
|
50
|
+
homepage_uri: https://github.com/fabian12943/badged_ids
|
51
|
+
source_code_uri: https://github.com/fabian12943/badged_ids
|
52
|
+
changelog_uri: https://github.com/fabian12943/badged_ids/blob/main/CHANGELOG.md
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.7.0
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubygems_version: 3.5.3
|
69
|
+
signing_key:
|
70
|
+
specification_version: 4
|
71
|
+
summary: Badged-IDs generates and persists unguessable IDs with friendly prefixes
|
72
|
+
for your models
|
73
|
+
test_files: []
|