encoded_id-rails 1.0.0.rc1 → 1.0.0.rc7
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/CHANGELOG.md +97 -18
- data/LICENSE.txt +1 -1
- data/README.md +81 -473
- data/context/encoded_id-rails.md +651 -0
- data/context/encoded_id.md +437 -0
- data/lib/encoded_id/rails/active_record_finders.rb +54 -0
- data/lib/encoded_id/rails/annotated_id.rb +14 -9
- data/lib/encoded_id/rails/annotated_id_parser.rb +9 -1
- data/lib/encoded_id/rails/coder.rb +55 -10
- data/lib/encoded_id/rails/composite_id_base.rb +39 -0
- data/lib/encoded_id/rails/configuration.rb +66 -10
- data/lib/encoded_id/rails/encoder_methods.rb +30 -7
- data/lib/encoded_id/rails/finder_methods.rb +11 -0
- data/lib/encoded_id/rails/model.rb +60 -7
- data/lib/encoded_id/rails/path_param.rb +8 -0
- data/lib/encoded_id/rails/persists.rb +55 -9
- data/lib/encoded_id/rails/query_methods.rb +21 -4
- data/lib/encoded_id/rails/railtie.rb +13 -0
- data/lib/encoded_id/rails/salt.rb +8 -0
- data/lib/encoded_id/rails/slugged_id.rb +14 -9
- data/lib/encoded_id/rails/slugged_id_parser.rb +9 -1
- data/lib/encoded_id/rails/slugged_path_param.rb +8 -0
- data/lib/encoded_id/rails.rb +11 -6
- data/lib/generators/encoded_id/rails/install_generator.rb +36 -2
- data/lib/generators/encoded_id/rails/templates/{encoded_id.rb → hashids_encoded_id.rb} +49 -5
- data/lib/generators/encoded_id/rails/templates/sqids_encoded_id.rb +116 -0
- metadata +16 -24
- data/.devcontainer/Dockerfile +0 -17
- data/.devcontainer/compose.yml +0 -10
- data/.devcontainer/devcontainer.json +0 -12
- data/.standard.yml +0 -3
- data/Appraisals +0 -9
- data/Gemfile +0 -24
- data/Rakefile +0 -20
- data/Steepfile +0 -4
- data/gemfiles/.bundle/config +0 -2
- data/gemfiles/rails_7.2.gemfile +0 -19
- data/gemfiles/rails_8.0.gemfile +0 -19
- data/lib/encoded_id/rails/version.rb +0 -7
- data/rbs_collection.yaml +0 -24
- data/sig/encoded_id/rails.rbs +0 -141
data/README.md
CHANGED
|
@@ -1,533 +1,141 @@
|
|
|
1
|
-
# EncodedId::Rails
|
|
1
|
+
# EncodedId and EncodedId::Rails
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+

|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
`encoded_id` lets you encode numerical or hex IDs into obfuscated strings that can be used in URLs.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
`encoded_id-rails` is a Rails integration that provides additional features for using `encoded_id` with ActiveRecord models.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
It's one of the most, if not _the_ most, feature complete gem of its kind!
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
- 💅 supports slugged IDs (eg `my-cool-product-name--p5w9-z27j`) that are URL friendly (assuming your alphabet is too)
|
|
13
|
-
- 🔖 supports annotated IDs to help identify the model the encoded ID belongs to (eg for a `User` the encoded ID might be `user_p5w9-z27j`)
|
|
14
|
-
- 👓 encoded string can be split into groups of letters to improve human-readability (eg `abcd-efgh`)
|
|
15
|
-
- 👥 supports multiple IDs encoded in one encoded string (eg imagine the encoded ID `7aq60zqw` might decode to two IDs `[78, 45]`)
|
|
16
|
-
- 🔡 supports custom alphabets for the encoded string (at least 16 characters needed)
|
|
17
|
-
- by default uses a variation of the Crockford reduced character set (https://www.crockford.com/base32.html)
|
|
18
|
-
- easily confused characters (eg i and j, 0 and O, 1 and I etc) are mapped to counterpart characters, to
|
|
19
|
-
help avoid common readability mistakes when reading/sharing
|
|
20
|
-
- built-in profanity limitation
|
|
12
|
+
👉 **Full documentation available at [encoded-id.onrender.com](https://encoded-id.onrender.com)**
|
|
21
13
|
|
|
22
|
-
|
|
14
|
+
## Key Features
|
|
23
15
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
16
|
+
* 🔄 **Reversible** - Encoded IDs can be decoded back to the original values
|
|
17
|
+
* 👥 **Multiple IDs** - Encode multiple numeric IDs in one string
|
|
18
|
+
* 🚀 **Choose your encoding** - Supports `Sqids` (default) and `Hashids`, or use your own custom encoder
|
|
19
|
+
* 👓 **Human-readable** - Character grouping & character mappings of easily confused characters for better readability
|
|
20
|
+
* 🔡 **Custom alphabets** - Use your preferred character set, or a provided default
|
|
21
|
+
* 🚗 **Performance** - Uses an optimized `Hashids` encoder (compared to `hashids` gem) for better performance and less memory usage, and have pushed performance improvements to `Sqids` as well
|
|
22
|
+
* 🤬 **Blocklist filtering** - Built-in word blocklist support with configurable modes and optional default lists
|
|
27
23
|
|
|
28
|
-
|
|
29
|
-
class User < ApplicationRecord
|
|
30
|
-
include EncodedId::Model
|
|
31
|
-
|
|
32
|
-
# An optional slug for the encoded ID string. This is prepended to the encoded ID string, and is solely
|
|
33
|
-
# to make the ID human friendly, or useful in URLs. It is not required for finding records by encoded ID.
|
|
34
|
-
def name_for_encoded_id_slug
|
|
35
|
-
full_name
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# An optional prefix on the encoded ID string to help identify the model it belongs to.
|
|
39
|
-
# Default is to use model's parameterized name, but can be overridden, or disabled.
|
|
40
|
-
# Note it is not required for finding records by encoded ID.
|
|
41
|
-
def annotation_for_encoded_id
|
|
42
|
-
"usr"
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# You can find by the encoded ID
|
|
47
|
-
user = User.find_by_encoded_id("p5w9-z27j") # => #<User id: 78>
|
|
48
|
-
user.encoded_id # => "usr_p5w9-z27j"
|
|
49
|
-
user.slugged_encoded_id # => "bob-smith--usr_p5w9-z27j"
|
|
50
|
-
|
|
51
|
-
# You can find by a slugged & annotated encoded ID
|
|
52
|
-
user == User.find_by_encoded_id("bob-smith--usr_p5w9-z27j") # => true
|
|
53
|
-
|
|
54
|
-
# Encoded IDs can encode multiple IDs at the same time
|
|
55
|
-
users = User.find_all_by_encoded_id("7aq60zqw") # => [#<User id: 78>, #<User id: 45>]
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Why this gem?
|
|
59
|
-
|
|
60
|
-
With this gem you can easily obfuscate your IDs in your URLs, and still be able to find records by using
|
|
61
|
-
the encoded IDs. The encoded IDs are meant to be somewhat human friendly, to make communication easier
|
|
62
|
-
when sharing encoded IDs with other people.
|
|
63
|
-
|
|
64
|
-
* Hashids are reversible, no need to persist the generated Id
|
|
65
|
-
* we don't override any AR methods. `encoded_id`s are intentionally **not interchangeable** with normal record `id`s
|
|
66
|
-
(ie you can't use `.find` to find by encoded ID or record ID, you must be explicit)
|
|
67
|
-
* we support slugged IDs (eg `my-amazing-product--p5w9-z27j`)
|
|
68
|
-
* we support multiple model IDs encoded in one `EncodedId` (eg `7aq6-0zqw` might decode to `[78, 45]`)
|
|
69
|
-
* the gem is configurable
|
|
70
|
-
* encoded IDs can be stable across environments, or not (you can set the salt to different values per environment)
|
|
71
|
-
|
|
72
|
-
## Coming in future (?)
|
|
73
|
-
|
|
74
|
-
- support for UUIDs for IDs (which will be encoded as an array of integers)
|
|
75
|
-
|
|
76
|
-
## Installation
|
|
77
|
-
|
|
78
|
-
Install the gem and add to the application's Gemfile by executing:
|
|
79
|
-
|
|
80
|
-
$ bundle add encoded_id-rails
|
|
81
|
-
|
|
82
|
-
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
83
|
-
|
|
84
|
-
$ gem install encoded_id-rails
|
|
85
|
-
|
|
86
|
-
Then run the generator to add the initializer:
|
|
87
|
-
|
|
88
|
-
rails g encoded_id:rails:install
|
|
89
|
-
|
|
90
|
-
If you plan to use the `EncodedId::Rails::Persists` module to persist encoded IDs, you can generate the necessary migration:
|
|
91
|
-
|
|
92
|
-
rails g encoded_id:rails:add_columns User Product # Add to multiple models
|
|
93
|
-
|
|
94
|
-
This will create a migration that adds the required columns and indexes to the specified models.
|
|
95
|
-
|
|
96
|
-
## Usage
|
|
24
|
+
### Rails Integration Features
|
|
97
25
|
|
|
98
|
-
|
|
26
|
+
* 🏷️ **ActiveRecord integration** - Use with ActiveRecord models
|
|
27
|
+
* 🔑 **Per-model configuration** - Use custom salt and encoding settings per model
|
|
28
|
+
* 💅 **Slugged IDs** - URL-friendly slugs like `my-product--p5w9-z27j`
|
|
29
|
+
* 🔖 **Annotated IDs** - Model type indicators like `user_p5w9-z27j` (default behavior)
|
|
30
|
+
* 🔍 **Finder methods** - `find_by_encoded_id`, `find_by_encoded_id!`, `find_all_by_encoded_id`, `where_encoded_id`
|
|
31
|
+
* 🛣️ **URL params** - `to_param` automatically uses encoded IDs
|
|
32
|
+
* 🔒 **Safe defaults** - Limits on encoded ID lengths to prevent CPU and memory-intensive encode/decodes when used in URLs
|
|
33
|
+
* 💾 **Persistence** - Optional database persistence for efficient lookups
|
|
99
34
|
|
|
100
|
-
The install generator will create an initializer file [`config/initializers/encoded_id.rb`](https://github.com/stevegeek/encoded_id-rails/blob/main/lib/generators/encoded_id/rails/templates/encoded_id.rb). It is documented
|
|
101
|
-
and should be self-explanatory.
|
|
102
35
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
- a global salt needed to generate the encoded IDs (if you dont use a global salt, you can set a salt per model)
|
|
106
|
-
- the size of the character groups in the encoded string (default is 4)
|
|
107
|
-
- the separator between the character groups (default is '-')
|
|
108
|
-
- the alphabet used to generate the encoded string (default is a variation of the Crockford reduced character set)
|
|
109
|
-
- the minimum length of the encoded ID string (default is 8 characters)
|
|
110
|
-
- whether models automatically override `to_param` to return the encoded ID (default is false)
|
|
111
|
-
|
|
112
|
-
### ActiveRecord model setup
|
|
113
|
-
|
|
114
|
-
Include `EncodedId::Model` in your model and optionally specify a encoded id salt (or not if using a global one):
|
|
36
|
+
## Quick Example
|
|
115
37
|
|
|
116
38
|
```ruby
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def encoded_id_salt
|
|
122
|
-
"my-user-model-salt"
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
# ...
|
|
126
|
-
end
|
|
127
|
-
```
|
|
39
|
+
# Using Hashids encoder (requires salt)
|
|
40
|
+
coder = ::EncodedId::ReversibleId.hashid(salt: "my-salt")
|
|
41
|
+
coder.encode(123)
|
|
42
|
+
# => "m3pm-8anj"
|
|
128
43
|
|
|
129
|
-
|
|
44
|
+
# The encoded strings are reversible
|
|
45
|
+
coder.decode("m3pm-8anj")
|
|
46
|
+
# => [123]
|
|
130
47
|
|
|
131
|
-
|
|
48
|
+
# Supports encoding multiple IDs at once
|
|
49
|
+
coder.encode([78, 45])
|
|
50
|
+
# => "ny9y-sd7p"
|
|
132
51
|
|
|
133
|
-
|
|
134
|
-
|
|
52
|
+
# Using Sqids encoder (default, no salt required)
|
|
53
|
+
sqids_coder = ::EncodedId::ReversibleId.sqids
|
|
54
|
+
sqids_coder.encode(123)
|
|
55
|
+
# => (encoded value varies)
|
|
135
56
|
|
|
136
|
-
|
|
137
|
-
return the encoded ID string instead of the record ID by default.
|
|
138
|
-
|
|
139
|
-
```ruby
|
|
57
|
+
# Can also be used with ActiveRecord models
|
|
140
58
|
class User < ApplicationRecord
|
|
141
|
-
include EncodedId::Model
|
|
142
|
-
include EncodedId::SluggedPathParam
|
|
59
|
+
include EncodedId::Rails::Model
|
|
143
60
|
|
|
61
|
+
# Optional: define method to provide slug for encoded ID
|
|
144
62
|
def name_for_encoded_id_slug
|
|
145
63
|
full_name
|
|
146
64
|
end
|
|
147
65
|
end
|
|
148
66
|
|
|
149
|
-
|
|
150
|
-
|
|
67
|
+
# Find by encoded ID
|
|
68
|
+
user = User.find_by_encoded_id("p5w9-z27j") # => #<User id: 78>
|
|
69
|
+
user.encoded_id # => "user_p5w9-z27j"
|
|
70
|
+
user.slugged_encoded_id # => "bob-smith--user_p5w9-z27j"
|
|
151
71
|
```
|
|
152
72
|
|
|
153
|
-
|
|
73
|
+
## Standalone Gem
|
|
154
74
|
|
|
155
|
-
```ruby
|
|
156
|
-
# In config/initializers/encoded_id.rb
|
|
157
|
-
EncodedId::Rails.configure do |config|
|
|
158
|
-
# ... other configuration options
|
|
159
|
-
config.model_to_param_returns_encoded_id = true
|
|
160
|
-
end
|
|
161
75
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
end
|
|
76
|
+
```bash
|
|
77
|
+
# Add to Gemfile
|
|
78
|
+
bundle add encoded_id
|
|
166
79
|
|
|
167
|
-
|
|
168
|
-
|
|
80
|
+
# Or install directly
|
|
81
|
+
gem install encoded_id
|
|
169
82
|
```
|
|
170
83
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
### Persisting encoded IDs
|
|
84
|
+
See the [EncodedId API](https://encoded-id.onrender.com/docs/encoded_id/api) documentation for more details.
|
|
174
85
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
To use this feature, you can either:
|
|
178
|
-
|
|
179
|
-
1. Use the generator to create a migration for your models:
|
|
86
|
+
## Rails Integration Gem
|
|
180
87
|
|
|
181
88
|
```bash
|
|
182
|
-
|
|
183
|
-
|
|
89
|
+
# Add to Gemfile
|
|
90
|
+
bundle add encoded_id-rails
|
|
184
91
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
```ruby
|
|
188
|
-
add_column :users, :normalized_encoded_id, :string
|
|
189
|
-
add_column :users, :prefixed_encoded_id, :string
|
|
190
|
-
add_index :users, :normalized_encoded_id, unique: true
|
|
191
|
-
add_index :users, :prefixed_encoded_id, unique: true
|
|
92
|
+
# Then run the generator
|
|
93
|
+
rails g encoded_id:rails:install
|
|
192
94
|
```
|
|
193
95
|
|
|
194
|
-
|
|
96
|
+
See the [Rails Integration](https://encoded-id.onrender.com/docs/encoded_id_rails) documentation for more details.
|
|
195
97
|
|
|
196
|
-
|
|
197
|
-
class User < ApplicationRecord
|
|
198
|
-
include EncodedId::Model
|
|
199
|
-
include EncodedId::Rails::Persists
|
|
200
|
-
end
|
|
201
|
-
```
|
|
98
|
+
## Security Note
|
|
202
99
|
|
|
203
|
-
|
|
100
|
+
**Encoded IDs are not secure**. They are meant to provide obfuscation, not encryption. Do not use them as a security mechanism.
|
|
204
101
|
|
|
205
|
-
1.
|
|
206
|
-
2. Store the complete encoded ID (with prefix if any) in the `prefixed_encoded_id` column
|
|
207
|
-
3. Add validations to ensure these columns are unique
|
|
208
|
-
4. Make these columns readonly after creation
|
|
209
|
-
5. Automatically update the persisted encoded IDs when the record is created
|
|
210
|
-
6. Ensure encoded IDs are reset when a record is duplicated
|
|
211
|
-
7. Provide safeguards to prevent inconsistencies
|
|
102
|
+
As of version 1.0.0, `Sqids` is the default encoder. `Hashids` is still supported but is officially deprecated by the Hashids project in favor of Sqids.
|
|
212
103
|
|
|
213
|
-
|
|
104
|
+
Read more about the security implications: [Hashids expose salt value](https://www.sjoerdlangkemper.nl/2023/11/25/hashids-expose-salt-value/) (note: this specifically applies to Hashids encoder)
|
|
214
105
|
|
|
215
|
-
|
|
106
|
+
## Compare to Alternate Gems
|
|
216
107
|
|
|
217
|
-
|
|
108
|
+
- [prefixed_ids](https://github.com/excid3/prefixed_ids)
|
|
109
|
+
- [obfuscate_id](https://github.com/namick/obfuscate_id)
|
|
110
|
+
- [friendly_id](https://github.com/norman/friendly_id)
|
|
111
|
+
- [with_uid](https://github.com/SPBTV/with_uid)
|
|
112
|
+
- [bullet_train-obfuscates_id](https://github.com/bullet-train-co/bullet_train-core/blob/main/bullet_train-obfuscates_id/app/models/concerns/obfuscates_id.rb)
|
|
218
113
|
|
|
219
|
-
|
|
220
|
-
# Creating a record automatically sets the encoded IDs
|
|
221
|
-
user = User.create(name: "Bob Smith")
|
|
222
|
-
user.normalized_encoded_id # => "p5w9z27j" (encoded ID without character grouping)
|
|
223
|
-
user.prefixed_encoded_id # => "user_p5w9-z27j" (complete encoded ID with prefix)
|
|
224
|
-
|
|
225
|
-
# You can use these in ActiveRecord queries now of course, eg
|
|
226
|
-
User.where(normalized_encoded_id: ["p5w9z27j", "7aq60zqw"])
|
|
227
|
-
|
|
228
|
-
# If you need to refresh the encoded ID (e.g., you changed the salt)
|
|
229
|
-
user.set_normalized_encoded_id!
|
|
230
|
-
|
|
231
|
-
# The module protects against direct changes to these attributes
|
|
232
|
-
user.normalized_encoded_id = "something-else"
|
|
233
|
-
user.save # This will raise ActiveRecord::ReadonlyAttributeError
|
|
234
|
-
```
|
|
114
|
+
For a detailed comparison, see the [Compared to Other Gems](https://encoded-id.onrender.com/docs/compared-to) documentation page.
|
|
235
115
|
|
|
236
116
|
## Documentation
|
|
237
117
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
Like `.find` but accepts an encoded ID string instead of an ID. Will return `nil` if no record is found.
|
|
241
|
-
|
|
242
|
-
```ruby
|
|
243
|
-
user = User.find_by_encoded_id("p5w9-z27j") # => #<User id: 78>
|
|
244
|
-
user.encoded_id # => "p5w9-z27j"
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
Note when an encoded ID string contains multiple IDs, this method will return the record for the first ID.
|
|
248
|
-
|
|
249
|
-
### `.find_by_encoded_id!`
|
|
250
|
-
|
|
251
|
-
Like `.find!` but accepts an encoded ID string instead of an ID. Raises `ActiveRecord::RecordNotFound` if no record is found.
|
|
252
|
-
|
|
253
|
-
```ruby
|
|
254
|
-
user = User.find_by_encoded_id!("p5w9-z27j") # => #<User id: 78>
|
|
255
|
-
|
|
256
|
-
# raises ActiveRecord::RecordNotFound
|
|
257
|
-
user = User.find_by_encoded_id!("encoded-id-that-is-not-found") # => ActiveRecord::RecordNotFound
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
Note when an encoded ID string contains multiple IDs, this method will return the record for the first ID.
|
|
261
|
-
|
|
262
|
-
### `.find_all_by_encoded_id`
|
|
263
|
-
|
|
264
|
-
Like `.find_by_encoded_id` but when an encoded ID string contains multiple IDs,
|
|
265
|
-
this method will return an array of records.
|
|
266
|
-
|
|
267
|
-
### `.find_all_by_encoded_id!`
|
|
268
|
-
|
|
269
|
-
Like `.find_by_encoded_id!` but when an encoded ID string contains multiple IDs,
|
|
270
|
-
this method will return an array of records.
|
|
271
|
-
|
|
272
|
-
### `.where_encoded_id`
|
|
273
|
-
|
|
274
|
-
A helper for creating relations. Decodes the encoded ID string before passing it to `.where`.
|
|
275
|
-
|
|
276
|
-
```ruby
|
|
277
|
-
encoded_id = User.encode_encoded_id([user1.id, user2.id]) # => "7aq6-0zqw"
|
|
278
|
-
User.where(active: true)
|
|
279
|
-
.where_encoded_id(encoded_id)
|
|
280
|
-
.map(&:name) # => ["Bob Smith", "Jane Doe"]
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### `.encode_encoded_id`
|
|
284
|
-
|
|
285
|
-
Encodes an ID or array of IDs into an encoded ID string.
|
|
286
|
-
|
|
287
|
-
```ruby
|
|
288
|
-
User.encode_encoded_id(78) # => "p5w9-z27j"
|
|
289
|
-
User.encode_encoded_id([78, 45]) # => "7aq6-0zqw"
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### `.decode_encoded_id`
|
|
293
|
-
|
|
294
|
-
Decodes an encoded ID string into an array of IDs.
|
|
295
|
-
|
|
296
|
-
```ruby
|
|
297
|
-
User.decode_encoded_id("p5w9-z27j") # => [78]
|
|
298
|
-
User.decode_encoded_id("7aq6-0zqw") # => [78, 45]
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
### `.encoded_id_salt`
|
|
302
|
-
|
|
303
|
-
Returns the salt used to generate the encoded ID string. If not defined, the global salt is used
|
|
304
|
-
with `EncodedId::Rails::Salt` to generate a model specific one.
|
|
305
|
-
|
|
306
|
-
```ruby
|
|
307
|
-
User.encoded_id_salt # => "User/the-salt-from-the-initializer"
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
Otherwise override this method to return a salt specific to the model.
|
|
311
|
-
|
|
312
|
-
```ruby
|
|
313
|
-
class User < ApplicationRecord
|
|
314
|
-
include EncodedId::Model
|
|
315
|
-
|
|
316
|
-
def encoded_id_salt
|
|
317
|
-
"my-user-model-salt"
|
|
318
|
-
end
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
User.encoded_id_salt # => "my-user-model-salt"
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### `#encoded_id_hash`
|
|
325
|
-
|
|
326
|
-
Returns only the encoded 'hashId' part of the encoded ID for the record (without any annotation):
|
|
327
|
-
|
|
328
|
-
```ruby
|
|
329
|
-
user = User.create(name: "Bob Smith")
|
|
330
|
-
user.encoded_id_hash # => "p5w9-z27j"
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
### `#encoded_id`
|
|
335
|
-
|
|
336
|
-
Returns the encoded ID for the record, with an annotation (if it is enabled):
|
|
337
|
-
|
|
338
|
-
```ruby
|
|
339
|
-
user = User.create(name: "Bob Smith")
|
|
340
|
-
user.encoded_id # => "user_p5w9-z27j"
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
By default, the annotation comes from the underscored model name. However, you can change this by either:
|
|
344
|
-
|
|
345
|
-
- overriding `#annotation_for_encoded_id` on the model
|
|
346
|
-
- overriding `#annotation_for_encoded_id` on all models via your `ApplicationRecord`
|
|
347
|
-
- change the method called to get the annotation via setting the `annotation_method_name` config options in your initializer
|
|
348
|
-
- disable the annotation via setting the `annotation_method_name` config options in your initializer to `nil`
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
Examples:
|
|
352
|
-
|
|
353
|
-
```ruby
|
|
354
|
-
EncodedId::Rails.configuration.annotation_method_name = :name
|
|
355
|
-
user.encoded_id # => "bob_smith_p5w9-z27j"
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
```ruby
|
|
359
|
-
EncodedId::Rails.configuration.annotation_method_name = nil
|
|
360
|
-
user.encoded_id # => "p5w9-z27j"
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
```ruby
|
|
364
|
-
class User < ApplicationRecord
|
|
365
|
-
include EncodedId::Model
|
|
366
|
-
|
|
367
|
-
def annotation_for_encoded_id
|
|
368
|
-
"foo"
|
|
369
|
-
end
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
user = User.create(name: "Bob Smith")
|
|
373
|
-
user.encoded_id # => "foo_p5w9-z27j"
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
Note that you can also configure the annotation separator via the `annotated_id_separator` config option in your initializer,
|
|
377
|
-
but it must be set to a string that only contains character that are not part of the alphabet used to encode the ID.
|
|
378
|
-
|
|
379
|
-
```ruby
|
|
380
|
-
EncodedId::Rails.configuration.annotated_id_separator = "^^"
|
|
381
|
-
user.encoded_id # => "foo^^p5w9-z27j"
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
### `#slugged_encoded_id`
|
|
385
|
-
|
|
386
|
-
Use the `slugged_encoded_id` instance method to get the slugged version of the encoded ID for the record.
|
|
387
|
-
|
|
388
|
-
```ruby
|
|
389
|
-
user = User.create(name: "Bob Smith")
|
|
390
|
-
user.slugged_encoded_id # => "bob-smith--p5w9-z27j"
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
Calls `#name_for_encoded_id_slug` on the record to get the slug part of the encoded ID.
|
|
394
|
-
By default, `#name_for_encoded_id_slug` raises, and must be overridden, or configured via the `slug_value_method_name` config option in your initializer:
|
|
395
|
-
|
|
396
|
-
```ruby
|
|
397
|
-
class User < ApplicationRecord
|
|
398
|
-
include EncodedId::Model
|
|
399
|
-
|
|
400
|
-
# Assuming user has a name attribute
|
|
401
|
-
def name_for_encoded_id_slug
|
|
402
|
-
name
|
|
403
|
-
end
|
|
404
|
-
end
|
|
405
|
-
|
|
406
|
-
user = User.create(name: "Bob Smith")
|
|
407
|
-
user.slugged_encoded_id # => "bob-smith--p5w9-z27j"
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
You can optionally override this method to define your own slug:
|
|
411
|
-
|
|
412
|
-
```ruby
|
|
413
|
-
class User < ApplicationRecord
|
|
414
|
-
include EncodedId::Model
|
|
415
|
-
|
|
416
|
-
def name_for_encoded_id_slug
|
|
417
|
-
superhero_name
|
|
418
|
-
end
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
user = User.create(superhero_name: "Super Dev")
|
|
422
|
-
user.slugged_encoded_id # => "super-dev--37nw-8nh7"
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
Configure the method called by setting the `slug_value_method_name` config option in your initializer:
|
|
426
|
-
|
|
427
|
-
```ruby
|
|
428
|
-
EncodedId::Rails.configuration.slug_value_method_name = :name
|
|
429
|
-
user.slugged_encoded_id # => "bob-smith--p5w9-z27j"
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
Note that you can also configure the slug separator via the `slugged_id_separator` config option in your initializer,
|
|
433
|
-
but it must be set to a string that only contains character that are not part of the alphabet used to encode the ID.
|
|
434
|
-
|
|
435
|
-
```ruby
|
|
436
|
-
EncodedId::Rails.configuration.slugged_id_separator = "***"
|
|
437
|
-
user.slugged_encoded_id # => "bob-smith***p5w9-z27j"
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
## To use on all models
|
|
441
|
-
|
|
442
|
-
Simply add the mixin to your `ApplicationRecord`:
|
|
443
|
-
|
|
444
|
-
```ruby
|
|
445
|
-
class ApplicationRecord < ActiveRecord::Base
|
|
446
|
-
self.abstract_class = true
|
|
447
|
-
include EncodedId::Model
|
|
448
|
-
|
|
449
|
-
...
|
|
450
|
-
end
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
However, I recommend you only use it on the models that need it.
|
|
454
|
-
|
|
455
|
-
## Example usage for a route and controller
|
|
456
|
-
|
|
457
|
-
```ruby
|
|
458
|
-
# Route
|
|
459
|
-
resources :users, param: :encoded_id, only: [:show]
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
```ruby
|
|
463
|
-
# Model
|
|
464
|
-
class User < ApplicationRecord
|
|
465
|
-
include EncodedId::Model
|
|
466
|
-
include EncodedId::PathParam
|
|
467
|
-
end
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
```ruby
|
|
471
|
-
# Controller
|
|
472
|
-
class UsersController < ApplicationController
|
|
473
|
-
def show
|
|
474
|
-
@user = User.find_by_encoded_id!(params[:encoded_id])
|
|
475
|
-
end
|
|
476
|
-
end
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
```erb
|
|
480
|
-
<%= link_to "User", user_path %>
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
## Performance Considerations
|
|
484
|
-
|
|
485
|
-
The performance of encoding and decoding IDs depends on several factors:
|
|
486
|
-
|
|
487
|
-
1. **ID Length**: The longer the minimum ID length specified in configuration (`id_length`), the slower the encoding and decoding process will be. This is because the underlying Hashids algorithm has to do more work to generate longer IDs. If performance is critical, consider using shorter ID lengths, but be aware of the security tradeoffs.
|
|
488
|
-
|
|
489
|
-
2. **Encoding Multiple IDs**: Encoding multiple IDs in a single string is more computationally expensive than encoding a single ID.
|
|
490
|
-
|
|
491
|
-
3. **Database Queries**: When using `find_by_encoded_id` or `where_encoded_id`, each lookup requires decoding first. Consider using the `Persists` module to store encoded IDs if this is an issue.
|
|
492
|
-
|
|
493
|
-
4. **Character Grouping**: Using character grouping with separators adds a small overhead to encoding and decoding.
|
|
494
|
-
|
|
495
|
-
For detailed performance metrics and benchmarks, refer to the [EncodedId gem documentation](https://github.com/stevegeek/encoded_id).
|
|
118
|
+
Visit [encoded-id.onrender.com](https://encoded-id.onrender.com) for comprehensive documentation including:
|
|
496
119
|
|
|
120
|
+
- [EncodedId Core Guide](https://encoded-id.onrender.com/docs/encoded_id/) - Installation, configuration, examples, and advanced topics
|
|
121
|
+
- [EncodedId Rails Guide](https://encoded-id.onrender.com/docs/encoded_id_rails/) - Rails integration, configuration, and examples
|
|
122
|
+
- [EncodedId Core API Reference](https://encoded-id.onrender.com/docs/encoded_id/api)
|
|
123
|
+
- [Rails Integration API Reference](https://encoded-id.onrender.com/docs/encoded_id_rails/api)
|
|
497
124
|
|
|
498
125
|
## Development
|
|
499
126
|
|
|
500
|
-
After checking out the repo, run `bin/setup` to install dependencies.
|
|
127
|
+
After checking out the repo, run `bin/setup` to install dependencies. Run `bundle exec rake test` to run the tests.
|
|
501
128
|
|
|
502
|
-
|
|
129
|
+
Run benchmarks with `bin/benchmark <type>` where type is one of: `ips`, `memory`, `comparison`, `profile`, `flamegraph`, or `stress_decode`.
|
|
503
130
|
|
|
504
|
-
|
|
505
|
-
bundle exec rake coverage
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
This will generate a coverage report in the `coverage` directory that you can open in your browser.
|
|
509
|
-
|
|
510
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
511
|
-
|
|
512
|
-
### Type check
|
|
513
|
-
|
|
514
|
-
First install dependencies:
|
|
515
|
-
|
|
516
|
-
```bash
|
|
517
|
-
rbs collection install
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
Then run:
|
|
521
|
-
|
|
522
|
-
```bash
|
|
523
|
-
steep check
|
|
524
|
-
```
|
|
131
|
+
### Documentation
|
|
525
132
|
|
|
133
|
+
Run `bundle exec rake website:build` to build or `bundle exec rake website:serve` to preview locally.
|
|
526
134
|
|
|
527
135
|
## Contributing
|
|
528
136
|
|
|
529
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/stevegeek/encoded_id
|
|
137
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/stevegeek/encoded_id.
|
|
530
138
|
|
|
531
139
|
## License
|
|
532
140
|
|
|
533
|
-
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
141
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|