encoded_id-rails 1.0.0.beta3 → 1.0.0.rc6

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -18
  3. data/LICENSE.txt +1 -1
  4. data/README.md +77 -368
  5. data/context/encoded_id-rails.md +433 -0
  6. data/context/encoded_id.md +283 -0
  7. data/lib/encoded_id/rails/active_record_finders.rb +52 -0
  8. data/lib/encoded_id/rails/annotated_id.rb +8 -0
  9. data/lib/encoded_id/rails/annotated_id_parser.rb +8 -1
  10. data/lib/encoded_id/rails/coder.rb +20 -2
  11. data/lib/encoded_id/rails/configuration.rb +45 -3
  12. data/lib/encoded_id/rails/encoder_methods.rb +9 -1
  13. data/lib/encoded_id/rails/finder_methods.rb +10 -0
  14. data/lib/encoded_id/rails/model.rb +65 -8
  15. data/lib/encoded_id/rails/path_param.rb +7 -0
  16. data/lib/encoded_id/rails/persists.rb +120 -0
  17. data/lib/encoded_id/rails/query_methods.rb +20 -4
  18. data/lib/encoded_id/rails/railtie.rb +13 -0
  19. data/lib/encoded_id/rails/salt.rb +7 -0
  20. data/lib/encoded_id/rails/slugged_id.rb +8 -0
  21. data/lib/encoded_id/rails/slugged_id_parser.rb +8 -1
  22. data/lib/encoded_id/rails/slugged_path_param.rb +7 -0
  23. data/lib/encoded_id/rails.rb +10 -6
  24. data/lib/generators/encoded_id/rails/USAGE +4 -0
  25. data/lib/generators/encoded_id/rails/add_columns_generator.rb +45 -0
  26. data/lib/generators/encoded_id/rails/templates/add_encoded_id_columns_migration.rb.erb +16 -0
  27. data/lib/generators/encoded_id/rails/templates/encoded_id.rb +28 -0
  28. metadata +27 -52
  29. data/.standard.yml +0 -3
  30. data/Appraisals +0 -14
  31. data/Gemfile +0 -18
  32. data/Rakefile +0 -14
  33. data/Steepfile +0 -4
  34. data/gemfiles/.bundle/config +0 -2
  35. data/gemfiles/rails_6.1.gemfile +0 -16
  36. data/gemfiles/rails_6.1.gemfile.lock +0 -130
  37. data/gemfiles/rails_7.0.gemfile +0 -16
  38. data/gemfiles/rails_7.0.gemfile.lock +0 -128
  39. data/gemfiles/rails_7.1.gemfile +0 -16
  40. data/gemfiles/rails_7.1.gemfile.lock +0 -140
  41. data/lib/encoded_id/rails/version.rb +0 -7
  42. data/rbs_collection.yaml +0 -24
  43. data/sig/encoded_id/rails.rbs +0 -141
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a38e6af88bf9343e2e4d22a82eb4c4d87766e962f3a8d330bf6aad1ad374639
4
- data.tar.gz: 3ea6b28d604d3f728da545d324f50b12845f2feb9b7ed83c32349e002cdb6c93
3
+ metadata.gz: 45d2f2c1637f43c14a714d4051ec7a1692a8267234ea90c302da97872b2da7b0
4
+ data.tar.gz: 26030ffcef1dc8798d0919a68faf4ec5bb6d17c3a28730eee0d2bb1e9ecb8e3e
5
5
  SHA512:
6
- metadata.gz: b03bc14efe460f8f479f109d32a4197c88cc85b72d87b7aa348e40057c4ae540728f5f3c383b943460ebbfdcfdd7e3173c363dbb423026386331fe17ea7e50e8
7
- data.tar.gz: 5a6f16dc29c1c43450f278e08b7c82e597e13a70b4ea5183cbcc97d690307c6b847b5fef8cd594cb0f1396aca685beac78a8c427826b2003a1b2820b319793a3
6
+ metadata.gz: 05ca59de2b281917cb214cfaeb9a94c7453aba4a64d8e89ac484a583030839a192d5242a774bc511e78d6667c47d11bca27bb3a0b096aefa6c2aad3e3c39ad84
7
+ data.tar.gz: e3cc3563234d3c13d10f34c55cc77b14f3a7c55e3b391d679d5c2239f39b272cd3e4a02c614f0638a20db815d1c425fd58c334a3b842d0cdb8c88a2c26e6e655
data/CHANGELOG.md CHANGED
@@ -1,31 +1,90 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [1.0.0] - (in beta)
3
+ ## [2.0.0.alpha1] - unreleased
4
4
 
5
5
  ### Breaking changes
6
6
 
7
- - Ruby 2.7.x support dropped. The minimum supported Ruby version is now 3.0.0.
8
- - `#encoded_id` now defaults to returning an 'annotated' ID, one in which a prefix is added to the encoded ID to indicate
9
- the 'type' of the record the ID represents. This can be disabled. IDs generated by older versions of this gem will
10
- decode correctly. But not that IDs generated by this version onwards will not decode correctly by older versions of this
11
- gem so make sure to disable annotation if you need to support older versions of this gem.
12
- - `#name_for_encoded_id_slug` no longer provides a default implementation, it is up to the user to define this method,
13
- or configure the gem to use a different method name.
14
- - `#slugged_encoded_id` no longer takes a `with:` parameter. To specify the name of the method to call to generate the
15
- slug, use the `slug_value_method_name` configuration option.
7
+ - `ReversibleId` now no longer downcases the encodedid input string by default on decode, ie the `decode` option `downcase` is now `false`. In a future release the `downcase` option will be removed.
8
+ - The default encoding engine is now `:sqids` to reflect the official "deprecated" status of `Hashid`s (see https://sqids.org/faq#why-hashids)
9
+ - Ruby < 3.2 support dropped. The minimum supported Ruby version is now 3.2.0
10
+
11
+ **Important!!: `:sqids` are not compatible with `:hashids`, DO NOT CHANGE FROM ONE TO THE OTHER AFTER GOING LIVE.**
12
+
13
+ ## [1.0.0.rc6] - 2025-11-17
14
+
15
+ ### Breaking changes
16
+
17
+ - Empty array inputs will now raise `InvalidInputError`
16
18
 
17
19
  ### Added
18
20
 
19
- - `#encoded_id_hash` has been added to return only the encoded ID without an annotation prefix. If annotation is disabled,
20
- this method is basically an alias to `#encoded_id`.
21
- - `.find_all_by_encoded_id` has been added to return all records matching the given encoded ID. This will return all
22
- matching records whose IDs are encoded in the encoded_id. Missing records are ignored.
23
- - `.find_all_by_encoded_id!` like `.find_all_by_encoded_id` but raises an `ActiveRecord::RecordNotFound` exception if
24
- *any* of the records are not found.
21
+ - Added support for [Sqids](https://sqids.org) as an alternative ID encoding engine. The default remains HashIds for backward compatibility.
22
+ - New encoder abstraction layer allows switching between HashIds and Sqids via the `encoder: :sqids` or `encoder: :hashids` parameter to `ReversibleId.new`.
23
+ - Support for blocklists in both HashIds and Sqids encoders to prevent generating IDs containing specific words. Use the `blocklist` parameter with a `Set` or `Array` of strings to `ReversibleId.new`. For Hashids encodings, an error will be raised if a generated ID contains a blocklisted word. For Sqids a new ID is generated that does not contain the block word.
24
+
25
+ ### Added (Rails integration)
26
+
27
+ - Merged `encoded_id-rails` gem into the monorepo
28
+ - Support for configuring the encoder and blocklist options in Rails through the configuration class
29
+ - `#encoded_id` now defaults to returning an 'annotated' ID, one in which a prefix is added to the encoded ID to indicate the 'type' of the record the ID represents. This can be disabled. IDs generated by older versions of this gem will decode correctly. But note that IDs generated by this version onwards will not decode correctly by older versions of this gem so make sure to disable annotation if you need to support older versions of this gem.
30
+ - New `EncodedId::Rails::Persists` module which adds hooks to the model to persist the encoded ID to the DB (see docs).
31
+ - `#encoded_id_hash` has been added to return only the encoded ID without an annotation prefix. If annotation is disabled, this method is basically an alias to `#encoded_id`.
32
+ - `.find_all_by_encoded_id` has been added to return all records matching the given encoded ID. This will return all matching records whose IDs are encoded in the encoded_id. Missing records are ignored.
33
+ - `.find_all_by_encoded_id!` like `.find_all_by_encoded_id` but raises an `ActiveRecord::RecordNotFound` exception if *any* of the records are not found.
34
+ - `Configuration#model_to_param_returns_encoded_id` to allow `EncodedId::Rails::Model` inclusion to also bring in `EncodedId::Rails::PathParam` automatically.
25
35
 
26
- ### Fixed
36
+ ### Changed (Rails integration)
37
+
38
+ - `#name_for_encoded_id_slug` no longer provides a default implementation, it is up to the user to define this method, or configure the gem to use a different method name.
39
+ - `#slugged_encoded_id` no longer takes a `with:` parameter. To specify the name of the method to call to generate the slug, use the `slug_value_method_name` configuration option.
40
+
41
+ ### Fixed (Rails integration)
27
42
 
28
43
  - `#decode_encoded_id` now raises if the encoded ID is not a string.
44
+ - Handle more cases where a record held onto a memoized `encoded_id` even though its `id` had changed
45
+
46
+ ## [1.0.0.rc5] - 2025-04-09
47
+
48
+ - `encoded_id` now uses its own implementation of `hashids` which is more efficient and has a smaller memory footprint. This massively reduces the GC churn in high-throughput applications. This is an implementation based on the original `hashids` gem but with many optimisations and improvements. Functionally it is identical to the original `hashids` gem.
49
+
50
+ ## [1.0.0.rc4] - 2024-04-29
51
+
52
+ - Add an optional `max_inputs_per_id` argument to `ReversibleId`, thanks to [@avcwisesa](https://github.com/avcwisesa)
53
+ - The option `split_with:` can also now be set to nil to disable splitting of the encoded ID string
54
+
55
+ ## [1.0.0.rc3] - 2023-10-23
56
+
57
+ - Add an optional `max_length` argument to `ReversibleId`, thanks to [@jugglebird](https://github.com/jugglebird)
58
+ - Alphabet validations to prevent whitespace and null chars
59
+ - Add `Alphabet#to_a`, `Alphabet#to_s`, `Alphabet#size` and a custom `Alphabet#inspect`
60
+ - Fixes to input validations
61
+ - hashids are case-sensitive, as are `Alphabet`s, however `ReversibleId` was always `downcase`ing the encodedid input string on decode. A new option has been added to `decode` and `decode_hex`, `downcase`, which defaults to `true`. Thus, the default behaviour is unchanged, but you can opt out to allow mixed case encodedid decode. *Note:* In V2 this will default to `false`.
62
+
63
+ ## [1.0.0.rc2] - 2023-08-07
64
+
65
+ - `Alphabet` now has `#include?` and `#unique_charaters` methods
66
+
67
+ ## [1.0.0.rc1] - 2023-08-06
68
+
69
+ - Improved RBS definitions
70
+ - Improved test coverage
71
+
72
+ ## [0.4.0] - 2022-12-04
73
+
74
+ - Support custom 'split' character which must not be in the alphabet
75
+ - Ability to provide a custom character equivalence mapping
76
+
77
+ ## [0.3.0] - 2022-10-12
78
+
79
+ - Fix splitting of encoded ID string
80
+ - Checks that integer values to be encoded are positive
81
+ - Experimental support for encoding hex strings
82
+
83
+ ## [0.1.0] - 2022-10-11
84
+
85
+ - Initial release
86
+
87
+ ## Rails Integration History
29
88
 
30
89
  ## [0.6.2] - 2023-02-09
31
90
 
@@ -64,4 +123,4 @@
64
123
 
65
124
  ## [0.1.0] - 2022-11-17
66
125
 
67
- - Initial release
126
+ - Initial release of Rails integration
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2022 Stephen Ierodiaconou
3
+ Copyright (c) 2022-2024 Stephen Ierodiaconou
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,421 +1,130 @@
1
- # EncodedId::Rails (`encoded_id-rails`)
1
+ # EncodedId and EncodedId::Rails
2
2
 
3
- `EncodedId::Rails` lets you turn numeric or hex **IDs into reversible and human friendly obfuscated strings**. The gem brings [EncodedId](https://github.com/stevegeek/encoded_id) to Rails and `ActiveRecord` models.
3
+ ![Coverage](badges/coverage_badge_total.svg)
4
+ ![RubyCritic](badges/rubycritic_badge_score.svg)
4
5
 
5
- You can use it in routes for example, to go from something like `/users/725` to `/users/bob-smith--usr_p5w9-z27j` with miminal effort.
6
+ `encoded_id` lets you encode numerical or hex IDs into obfuscated strings that can be used in URLs.
6
7
 
7
- ## Features
8
+ `encoded_id-rails` is a Rails integration that provides additional features for using `encoded_id` with ActiveRecord models.
8
9
 
9
- Under the hood it uses hashIds, but it offers more features.
10
+ 👉 **Full documentation available at [encoded-id.onrender.com](https://encoded-id.onrender.com)**
10
11
 
11
- - 🔄 encoded IDs are reversible (see [`encoded_id`](https://github.com/stevegeek/encoded_id))
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
- - build in profanity limitation
21
-
22
- The gem provides:
23
-
24
- - methods to mixin to ActiveRecord models which will allow you to encode and decode IDs, and find
25
- or query by encoded IDs
26
- - sensible defaults to allow you to get started out of the box
12
+ ## Quick Example
27
13
 
28
14
  ```ruby
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
-
73
- ## Coming in future (?)
74
-
75
- - support for UUIDs for IDs (which will be encoded as an array of integers)
76
-
77
- ## Installation
15
+ coder = ::EncodedId::ReversibleId.new(salt: "my-salt")
16
+ coder.encode(123)
17
+ # => "p5w9-z27j"
78
18
 
79
- Install the gem and add to the application's Gemfile by executing:
19
+ # The encoded strings are reversible
20
+ coder.decode("p5w9-z27j")
21
+ # => [123]
80
22
 
81
- $ bundle add encoded_id-rails
23
+ # Supports encoding multiple IDs at once
24
+ coder.encode([78, 45])
25
+ # => "z2j7-0dmw"
82
26
 
83
- If bundler is not being used to manage dependencies, install the gem by executing:
84
-
85
- $ gem install encoded_id-rails
86
-
87
- Then run the generator to add the initializer:
88
-
89
- rails g encoded_id:rails:install
90
-
91
- ## Usage
92
-
93
- ### Configuration
94
-
95
- 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
96
- and should be self-explanatory.
97
-
98
- You can configure:
99
-
100
- - a global salt needed to generate the encoded IDs (if you dont use a global salt, you can set a salt per model)
101
- - the size of the character groups in the encoded string (default is 4)
102
- - the separator between the character groups (default is '-')
103
- - the alphabet used to generate the encoded string (default is a variation of the Crockford reduced character set)
104
- - the minimum length of the encoded ID string (default is 8 characters)
105
-
106
- ### ActiveRecord model setup
107
-
108
- Include `EncodedId::Model` in your model and optionally specify a encoded id salt (or not if using a global one):
109
-
110
- ```ruby
27
+ # Can also be used with ActiveRecord models
111
28
  class User < ApplicationRecord
112
- include EncodedId::Model
113
-
114
- # and optionally the model's salt
115
- def encoded_id_salt
116
- "my-user-model-salt"
117
- end
118
-
119
- # ...
120
- end
121
- ```
122
-
123
- ### Optional mixins
124
-
125
- You can optionally include one of the following mixins to add default overrides to `#to_param`.
126
-
127
- - `EncodedId::PathParam`
128
- - `EncodedId::SluggedPathParam`
129
-
130
- This is so that an instance of the model can be used in path helpers and
131
- return the encoded ID string instead of the record ID by default.
132
-
133
- ```ruby
134
- class User < ApplicationRecord
135
- include EncodedId::Model
136
- include EncodedId::SluggedPathParam
137
-
29
+ include EncodedId::Rails::Model
30
+
31
+ # Optional slug for the encoded ID
138
32
  def name_for_encoded_id_slug
139
33
  full_name
140
34
  end
141
35
  end
142
36
 
143
- user = User.create(full_name: "Bob Smith")
144
- Rails.application.routes.url_helpers.user_path(user) # => "/users/bob-smith--p5w9-z27j"
145
- ```
146
-
147
- ## Documentation
148
-
149
- ### `.find_by_encoded_id`
150
-
151
- Like `.find` but accepts an encoded ID string instead of an ID. Will return `nil` if no record is found.
152
-
153
- ```ruby
154
- user = User.find_by_encoded_id("p5w9-z27j") # => #<User id: 78>
155
- user.encoded_id # => "p5w9-z27j"
156
- ```
157
-
158
- Note when an encoded ID string contains multiple IDs, this method will return the record for the first ID.
159
-
160
- ### `.find_by_encoded_id!`
161
-
162
- Like `.find!` but accepts an encoded ID string instead of an ID. Raises `ActiveRecord::RecordNotFound` if no record is found.
163
-
164
- ```ruby
165
- user = User.find_by_encoded_id!("p5w9-z27j") # => #<User id: 78>
166
-
167
- # raises ActiveRecord::RecordNotFound
168
- user = User.find_by_encoded_id!("encoded-id-that-is-not-found") # => ActiveRecord::RecordNotFound
169
- ```
170
-
171
- Note when an encoded ID string contains multiple IDs, this method will return the record for the first ID.
172
-
173
- ### `.find_all_by_encoded_id`
174
-
175
- Like `.find_by_encoded_id` but when an encoded ID string contains multiple IDs,
176
- this method will return an array of records.
177
-
178
- ### `.find_all_by_encoded_id!`
179
-
180
- Like `.find_by_encoded_id!` but when an encoded ID string contains multiple IDs,
181
- this method will return an array of records.
182
-
183
- ### `.where_encoded_id`
184
-
185
- A helper for creating relations. Decodes the encoded ID string before passing it to `.where`.
186
-
187
- ```ruby
188
- encoded_id = User.encode_encoded_id([user1.id, user2.id]) # => "p5w9-z27j"
189
- User.where(active: true)
190
- .where_encoded_id(encoded_id)
191
- .map(&:name) # => ["Bob Smith", "Jane Doe"]
192
- ```
193
-
194
- ### `.encode_encoded_id`
195
-
196
- Encodes an ID or array of IDs into an encoded ID string.
197
-
198
- ```ruby
199
- User.encode_encoded_id(78) # => "p5w9-z27j"
200
- User.encode_encoded_id([78, 45]) # => "7aq6-0zqw"
201
- ```
202
-
203
- ### `.decode_encoded_id`
204
-
205
- Decodes an encoded ID string into an array of IDs.
206
-
207
- ```ruby
208
- User.decode_encoded_id("p5w9-z27j") # => [78]
209
- User.decode_encoded_id("7aq6-0zqw") # => [78, 45]
210
- ```
211
-
212
- ### `.encoded_id_salt`
213
-
214
- Returns the salt used to generate the encoded ID string. If not defined, the global salt is used
215
- with `EncodedId::Rails::Salt` to generate a model specific one.
216
-
217
- ```ruby
218
- User.encoded_id_salt # => "User/the-salt-from-the-initializer"
219
- ```
220
-
221
- Otherwise override this method to return a salt specific to the model.
222
-
223
- ```ruby
224
- class User < ApplicationRecord
225
- include EncodedId::Model
226
-
227
- def encoded_id_salt
228
- "my-user-model-salt"
229
- end
230
- end
231
-
232
- User.encoded_id_salt # => "my-user-model-salt"
233
- ```
234
-
235
- ### `#encoded_id_hash`
236
-
237
- Returns only the encoded 'hashId' part of the encoded ID for the record:
238
-
239
- ```ruby
240
- user = User.create(name: "Bob Smith")
241
- user.encoded_id # => "p5w9-z27j"
242
- ```
243
-
244
-
245
- ### `#encoded_id`
246
-
247
- Returns the encoded ID for the record, with an annotation (if it is enabled):
248
-
249
- ```ruby
250
- user = User.create(name: "Bob Smith")
251
- user.encoded_id # => "user_p5w9-z27j"
252
- ```
253
-
254
- By default, the annotation comes from the underscored model name. However, you can change this by either:
255
-
256
- - overriding `#annotation_for_encoded_id` on the model
257
- - overriding `#annotation_for_encoded_id` on all models via your `ApplicationRecord`
258
- - change the method called to get the annotation via setting the `annotation_method_name` config options in your initializer
259
- - disable the annotation via setting the `annotation_method_name` config options in your initializer to `nil`
260
-
261
-
262
- Examples:
263
-
264
- ```ruby
265
- EncodedId::Rails.configuration.annotation_method_name = :name
266
- user.encoded_id # => "bob_smith_p5w9-z27j"
267
- ```
268
-
269
- ```ruby
270
- EncodedId::Rails.configuration.annotation_method_name = nil
271
- user.encoded_id # => "p5w9-z27j"
37
+ # Find by encoded ID
38
+ user = User.find_by_encoded_id("p5w9-z27j") # => #<User id: 78>
39
+ user.encoded_id # => "user_p5w9-z27j"
40
+ user.slugged_encoded_id # => "bob-smith--user_p5w9-z27j"
272
41
  ```
273
42
 
274
- ```ruby
275
- class User < ApplicationRecord
276
- include EncodedId::Model
277
-
278
- def annotation_for_encoded_id
279
- "foo"
280
- end
281
- end
282
-
283
- user = User.create(name: "Bob Smith")
284
- user.encoded_id # => "foo_p5w9-z27j"
285
- ```
43
+ ## Key Features
286
44
 
287
- Note that you can also configure the annotation separator via the `annotated_id_separator` config option in your initializer,
288
- but it must be set to a string that only contains character that are not part of the alphabet used to encode the ID.
45
+ * 🔄 **Reversible** - Encoded IDs can be decoded back to the original values
46
+ * 👥 **Multiple IDs** - Encode multiple numeric IDs in one string
47
+ * 🚀 **Choose your encoding** - Supports `Hashids` and `Sqids` out of the box, or use your own custom encoder
48
+ * 👓 **Human-readable** - Character grouping & character mappings of easily confused characters for better readability
49
+ * 🔡 **Custom alphabets** - Use your preferred character set, or a provided default
50
+ * 🚗 **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
51
+ * 🤬 **Profanity blocking** - Built-in word blocklist support and optional default lists
289
52
 
290
- ```ruby
291
- EncodedId::Rails.configuration.annotated_id_separator = "^^"
292
- user.encoded_id # => "foo^^p5w9-z27j"
293
- ```
53
+ ### Rails Integration Features
294
54
 
295
- ### `#slugged_encoded_id`
55
+ * 🏷️ **ActiveRecord integration** - Use with ActiveRecord models
56
+ * 🔑 **Per-model salt** - Use a custom salt for encoding per model
57
+ * 💅 **Slugged IDs** - URL-friendly slugs like `my-product--p5w9-z27j`
58
+ * 🔖 **Annotated IDs** - Model type indicators like `user_p5w9-z27j`
59
+ * 🔍 **Finder methods** - Find records using encoded IDs
60
+ * 🛣️ **URL params** - `to_param` with encoded IDs
61
+ * 🔒 **Safe defaults**: Limits on encoded ID lengths to prevent CPU and memory-intensive encode/decodes eg when used in URLs
62
+ * 💾 **Persistence** - Optional database persistence for efficient lookups
296
63
 
297
- Use the `slugged_encoded_id` instance method to get the slugged version of the encoded ID for the record.
298
64
 
299
- ```ruby
300
- user = User.create(name: "Bob Smith")
301
- user.slugged_encoded_id # => "bob-smith--p5w9-z27j"
302
- ```
65
+ ## Standalone Gem
303
66
 
304
- Calls `#name_for_encoded_id_slug` on the record to get the slug part of the encoded ID.
305
- 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:
306
67
 
307
- ```ruby
308
- class User < ApplicationRecord
309
- include EncodedId::Model
310
-
311
- # Assuming user has a name attribute
312
- def name_for_encoded_id_slug
313
- name
314
- end
315
- end
316
-
317
- user = User.create(name: "Bob Smith")
318
- user.slugged_encoded_id # => "bob-smith--p5w9-z27j"
319
- ```
320
-
321
- You can optionally override this method to define your own slug:
322
-
323
- ```ruby
324
- class User < ApplicationRecord
325
- include EncodedId::Model
326
-
327
- def name_for_encoded_id_slug
328
- superhero_name
329
- end
330
- end
68
+ ```bash
69
+ # Add to Gemfile
70
+ bundle add encoded_id
331
71
 
332
- user = User.create(superhero_name: "Super Dev")
333
- user.slugged_encoded_id # => "super-dev--37nw-8nh7"
72
+ # Or install directly
73
+ gem install encoded_id
334
74
  ```
335
75
 
336
- Configure the method called by setting the `slug_value_method_name` config option in your initializer:
76
+ See the [EncodedId API](https://encoded-id.onrender.com/docs/encoded_id/api) documentation for more details.
337
77
 
338
- ```ruby
339
- EncodedId::Rails.configuration.slug_value_method_name = :name
340
- user.slugged_encoded_id # => "bob-smith--p5w9-z27j"
341
- ```
78
+ ## Rails Integration Gem
342
79
 
343
- Note that you can also configure the slug separator via the `slugged_id_separator` config option in your initializer,
344
- but it must be set to a string that only contains character that are not part of the alphabet used to encode the ID.
80
+ ```bash
81
+ # Add to Gemfile
82
+ bundle add encoded_id-rails
345
83
 
346
- ```ruby
347
- EncodedId::Rails.configuration.annotated_id_separator = "***"
348
- user.encoded_id # => "bob-smith***p5w9-z27j"
84
+ # Then run the generator
85
+ rails g encoded_id:rails:install
349
86
  ```
350
87
 
351
- ## To use on all models
88
+ See the [Rails Integration](https://encoded-id.onrender.com/docs/encoded_id_rails) documentation for more details.
352
89
 
353
- Simply add the mixin to your `ApplicationRecord`:
90
+ ## Security Note
354
91
 
355
- ```ruby
356
- class ApplicationRecord < ActiveRecord::Base
357
- self.abstract_class = true
358
- include EncodedId::Model
92
+ **Encoded IDs are not secure**. They are meant to provide obfuscation, not encryption. Do not use them as a security mechanism.
359
93
 
360
- ...
361
- end
362
- ```
94
+ ## Compare to Alternate Gems
363
95
 
364
- However, I recommend you only use it on the models that need it.
96
+ - [prefixed_ids](https://github.com/excid3/prefixed_ids)
97
+ - [obfuscate_id](https://github.com/namick/obfuscate_id)
98
+ - [friendly_id](https://github.com/norman/friendly_id)
99
+ - [with_uid](https://github.com/SPBTV/with_uid)
100
+ - [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)
365
101
 
366
- ## Example usage for a route and controller
102
+ For a detailed comparison, see the [Compared to Other Gems](https://encoded-id.onrender.com/docs/compared-to) documentation page.
367
103
 
368
- ```ruby
369
- # Route
370
- resources :users, param: :encoded_id, only: [:show]
371
- ```
104
+ ## Documentation
372
105
 
373
- ```ruby
374
- # Model
375
- class User < ApplicationRecord
376
- include EncodedId::Model
377
- include EncodedId::PathParam
378
- end
379
- ```
106
+ Visit [encoded-id.onrender.com](https://encoded-id.onrender.com) for comprehensive documentation including:
380
107
 
381
- ```ruby
382
- # Controller
383
- class UsersController < ApplicationController
384
- def show
385
- @user = User.find_by_encoded_id!(params[:encoded_id])
386
- end
387
- end
388
- ```
389
-
390
- ```erb
391
- <%= link_to "User", user_path %>
392
- ```
108
+ - [EncodedId Core API](https://encoded-id.onrender.com/docs/encoded_id/api)
109
+ - [Rails Integration API](https://encoded-id.onrender.com/docs/encoded_id_rails/api)
110
+ - [Configuration Options](https://encoded-id.onrender.com/docs/encoded_id/configuration)
111
+ - [Examples](https://encoded-id.onrender.com/docs/encoded_id/examples)
112
+ - [Advanced Topics](https://encoded-id.onrender.com/docs/advanced-topics)
393
113
 
394
114
  ## Development
395
115
 
396
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
397
-
398
- 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).
399
-
400
- ### Type check
401
-
402
- First install dependencies:
116
+ After checking out the repo, run `bin/setup` to install dependencies. Run `bundle exec rake test` to run the tests.
403
117
 
404
- ```bash
405
- rbs collection install
406
- ```
407
-
408
- Then run:
118
+ Run benchmarks with `bin/benchmark <type>` where type is one of: `ips`, `memory`, `comparison`, `profile`, `flamegraph`, or `stress_decode`.
409
119
 
410
- ```bash
411
- steep check
412
- ```
120
+ ### Documentation
413
121
 
122
+ Run `bundle exec rake website:build` to build or `bundle exec rake website:serve` to preview locally.
414
123
 
415
124
  ## Contributing
416
125
 
417
- Bug reports and pull requests are welcome on GitHub at https://github.com/stevegeek/encoded_id-rails.
126
+ Bug reports and pull requests are welcome on GitHub at https://github.com/stevegeek/encoded_id.
418
127
 
419
128
  ## License
420
129
 
421
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
130
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).