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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +77 -18
- data/LICENSE.txt +1 -1
- data/README.md +77 -368
- data/context/encoded_id-rails.md +433 -0
- data/context/encoded_id.md +283 -0
- data/lib/encoded_id/rails/active_record_finders.rb +52 -0
- data/lib/encoded_id/rails/annotated_id.rb +8 -0
- data/lib/encoded_id/rails/annotated_id_parser.rb +8 -1
- data/lib/encoded_id/rails/coder.rb +20 -2
- data/lib/encoded_id/rails/configuration.rb +45 -3
- data/lib/encoded_id/rails/encoder_methods.rb +9 -1
- data/lib/encoded_id/rails/finder_methods.rb +10 -0
- data/lib/encoded_id/rails/model.rb +65 -8
- data/lib/encoded_id/rails/path_param.rb +7 -0
- data/lib/encoded_id/rails/persists.rb +120 -0
- data/lib/encoded_id/rails/query_methods.rb +20 -4
- data/lib/encoded_id/rails/railtie.rb +13 -0
- data/lib/encoded_id/rails/salt.rb +7 -0
- data/lib/encoded_id/rails/slugged_id.rb +8 -0
- data/lib/encoded_id/rails/slugged_id_parser.rb +8 -1
- data/lib/encoded_id/rails/slugged_path_param.rb +7 -0
- data/lib/encoded_id/rails.rb +10 -6
- data/lib/generators/encoded_id/rails/USAGE +4 -0
- data/lib/generators/encoded_id/rails/add_columns_generator.rb +45 -0
- data/lib/generators/encoded_id/rails/templates/add_encoded_id_columns_migration.rb.erb +16 -0
- data/lib/generators/encoded_id/rails/templates/encoded_id.rb +28 -0
- metadata +27 -52
- data/.standard.yml +0 -3
- data/Appraisals +0 -14
- data/Gemfile +0 -18
- data/Rakefile +0 -14
- data/Steepfile +0 -4
- data/gemfiles/.bundle/config +0 -2
- data/gemfiles/rails_6.1.gemfile +0 -16
- data/gemfiles/rails_6.1.gemfile.lock +0 -130
- data/gemfiles/rails_7.0.gemfile +0 -16
- data/gemfiles/rails_7.0.gemfile.lock +0 -128
- data/gemfiles/rails_7.1.gemfile +0 -16
- data/gemfiles/rails_7.1.gemfile.lock +0 -140
- data/lib/encoded_id/rails/version.rb +0 -7
- data/rbs_collection.yaml +0 -24
- data/sig/encoded_id/rails.rbs +0 -141
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 45d2f2c1637f43c14a714d4051ec7a1692a8267234ea90c302da97872b2da7b0
|
|
4
|
+
data.tar.gz: 26030ffcef1dc8798d0919a68faf4ec5bb6d17c3a28730eee0d2bb1e9ecb8e3e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 05ca59de2b281917cb214cfaeb9a94c7453aba4a64d8e89ac484a583030839a192d5242a774bc511e78d6667c47d11bca27bb3a0b096aefa6c2aad3e3c39ad84
|
|
7
|
+
data.tar.gz: e3cc3563234d3c13d10f34c55cc77b14f3a7c55e3b391d679d5c2239f39b272cd3e4a02c614f0638a20db815d1c425fd58c334a3b842d0cdb8c88a2c26e6e655
|
data/CHANGELOG.md
CHANGED
|
@@ -1,31 +1,90 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [2.0.0.alpha1] - unreleased
|
|
4
4
|
|
|
5
5
|
### Breaking changes
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
###
|
|
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
|
|
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
|
+
👉 **Full documentation available at [encoded-id.onrender.com](https://encoded-id.onrender.com)**
|
|
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
|
-
- 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
|
-
|
|
30
|
-
|
|
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
|
-
|
|
19
|
+
# The encoded strings are reversible
|
|
20
|
+
coder.decode("p5w9-z27j")
|
|
21
|
+
# => [123]
|
|
80
22
|
|
|
81
|
-
|
|
23
|
+
# Supports encoding multiple IDs at once
|
|
24
|
+
coder.encode([78, 45])
|
|
25
|
+
# => "z2j7-0dmw"
|
|
82
26
|
|
|
83
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
144
|
-
|
|
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
|
-
|
|
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
|
-
|
|
288
|
-
|
|
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
|
-
|
|
291
|
-
EncodedId::Rails.configuration.annotated_id_separator = "^^"
|
|
292
|
-
user.encoded_id # => "foo^^p5w9-z27j"
|
|
293
|
-
```
|
|
53
|
+
### Rails Integration Features
|
|
294
54
|
|
|
295
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
333
|
-
|
|
72
|
+
# Or install directly
|
|
73
|
+
gem install encoded_id
|
|
334
74
|
```
|
|
335
75
|
|
|
336
|
-
|
|
76
|
+
See the [EncodedId API](https://encoded-id.onrender.com/docs/encoded_id/api) documentation for more details.
|
|
337
77
|
|
|
338
|
-
|
|
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
|
-
|
|
344
|
-
|
|
80
|
+
```bash
|
|
81
|
+
# Add to Gemfile
|
|
82
|
+
bundle add encoded_id-rails
|
|
345
83
|
|
|
346
|
-
|
|
347
|
-
|
|
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
|
-
|
|
88
|
+
See the [Rails Integration](https://encoded-id.onrender.com/docs/encoded_id_rails) documentation for more details.
|
|
352
89
|
|
|
353
|
-
|
|
90
|
+
## Security Note
|
|
354
91
|
|
|
355
|
-
|
|
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
|
-
|
|
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
|
-
|
|
102
|
+
For a detailed comparison, see the [Compared to Other Gems](https://encoded-id.onrender.com/docs/compared-to) documentation page.
|
|
367
103
|
|
|
368
|
-
|
|
369
|
-
# Route
|
|
370
|
-
resources :users, param: :encoded_id, only: [:show]
|
|
371
|
-
```
|
|
104
|
+
## Documentation
|
|
372
105
|
|
|
373
|
-
|
|
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
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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).
|