encoded_id-rails 0.1.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.
Potentially problematic release.
This version of encoded_id-rails might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +21 -0
- data/README.md +85 -0
- data/Rakefile +14 -0
- data/Steepfile +6 -0
- data/gemfiles/rails_6.0.gemfile +11 -0
- data/gemfiles/rails_7.0.gemfile +11 -0
- data/lib/encoded_id/rails/configuration.rb +19 -0
- data/lib/encoded_id/rails/version.rb +7 -0
- data/lib/encoded_id/rails/with_encoded_id.rb +211 -0
- data/lib/encoded_id/rails.rb +23 -0
- data/lib/generators/encoded_id/rails/USAGE +3 -0
- data/lib/generators/encoded_id/rails/install_generator.rb +19 -0
- data/lib/generators/encoded_id/rails/templates/encoded_id.rb +37 -0
- data/rbs_collection.yaml +25 -0
- data/sig/encoded_id/rails.rbs +109 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b6f08a83b8af33caeaff9e8773d18ff826e6ead353efa52aed89e19d94b8bb75
|
4
|
+
data.tar.gz: 874279bb397caf6ec7fb5bfe5596cde2424195e58c7230cce986d7b3e5b51057
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bcaa0ef9e037f2e333b323846df8bc9daea30e58fd3b5cb906531bfe7bf3c79884e30dbb13d38be92a891c4cdc69effbf4b358f15c76dfb1eccbbc37284882a9
|
7
|
+
data.tar.gz: 82572b25da35bce009de4d00f98c61c9fc96f96ea2df93b722d73a3c2908793d43081e3ec25c4998ff92013eba3cdbcb32abf192757deff0252635317b5684ee
|
data/.standard.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in encoded_id-rails.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem "rake", "~> 13.0"
|
9
|
+
|
10
|
+
gem "minitest", "~> 5.0"
|
11
|
+
|
12
|
+
gem "standard", "~> 1.3"
|
13
|
+
|
14
|
+
gem "steep", "~> 1.2"
|
15
|
+
|
16
|
+
gem "sqlite3", "~> 1.5"
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2022 Stephen Ierodiaconou
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# EncodedId::Rails
|
2
|
+
|
3
|
+
EncodedId mixin for your ActiveRecord models.
|
4
|
+
|
5
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/encoded_id/rails`. To experiment with that code, run `bin/console` for an interactive prompt.
|
6
|
+
|
7
|
+
TODO: Delete this and the text above, and describe your gem
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
class User < ApplicationRecord
|
11
|
+
include EncodedId::WithEncodedId
|
12
|
+
|
13
|
+
def slug
|
14
|
+
full_name.parameterize
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
user = User.find_by_encoded_id("p5w9-z27j") # => #<User id: 78>
|
19
|
+
user.encoded_id # => "p5w9-z27j"
|
20
|
+
user.slugged_id # => "bob-smith--p5w9-z27j"
|
21
|
+
```
|
22
|
+
# Features
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
# Coming in future (?)
|
27
|
+
|
28
|
+
- support for UUIDs for IDs (which will be encoded as an array of integers)
|
29
|
+
|
30
|
+
## Why this?
|
31
|
+
|
32
|
+
* Hashids are reversible, no need to persist the generated Id
|
33
|
+
* we don't override any methods or mess with ActiveRecord
|
34
|
+
* we support slugged IDs (eg 'my-amazing-product--p5w9-z27j')
|
35
|
+
* we support multiple model IDs encoded in one `EncodedId` (eg '7aq6-0zqw' decodes to `[78, 45]`)
|
36
|
+
* we use a reduced character set (Crockford alphabet),
|
37
|
+
and ids split into groups of letters, ie we aim for 'human-readability'
|
38
|
+
* can be stable across environments, or not (you can set the salt to different values per environment)
|
39
|
+
|
40
|
+
## Installation
|
41
|
+
|
42
|
+
Install the gem and add to the application's Gemfile by executing:
|
43
|
+
|
44
|
+
$ bundle add encoded_id-rails
|
45
|
+
|
46
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
47
|
+
|
48
|
+
$ gem install encoded_id-rails
|
49
|
+
|
50
|
+
Then run the generator to add the initializer:
|
51
|
+
|
52
|
+
rails g encoded_id-rails:install
|
53
|
+
|
54
|
+
## Usage
|
55
|
+
|
56
|
+
TODO: Write usage instructions here
|
57
|
+
|
58
|
+
### Use on all models (but I recommend you don't)
|
59
|
+
|
60
|
+
Simply add the mixin to your `ApplicationRecord`:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
class ApplicationRecord < ActiveRecord::Base
|
64
|
+
self.abstract_class = true
|
65
|
+
include EncodedId::WithEncodedId
|
66
|
+
|
67
|
+
...
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
However, I recommend you only use it on the models that need it.
|
72
|
+
|
73
|
+
## Development
|
74
|
+
|
75
|
+
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.
|
76
|
+
|
77
|
+
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).
|
78
|
+
|
79
|
+
## Contributing
|
80
|
+
|
81
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/encoded_id-rails.
|
82
|
+
|
83
|
+
## License
|
84
|
+
|
85
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/testtask"
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs << "test"
|
8
|
+
t.libs << "lib"
|
9
|
+
t.test_files = FileList["test/**/test_*.rb"]
|
10
|
+
end
|
11
|
+
|
12
|
+
require "standard/rake"
|
13
|
+
|
14
|
+
task default: %i[test standard]
|
data/Steepfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem "sqlite3"
|
4
|
+
gem "activesupport", "~> 6.1.7", ">= 6.1.0"
|
5
|
+
gem "activerecord", "~> 6.1.7", ">= 6.1.0"
|
6
|
+
gem "rake", "~> 13.0"
|
7
|
+
gem "minitest", "~> 5.0"
|
8
|
+
gem "standard", "~> 1.3"
|
9
|
+
gem "steep", "~> 1.2"
|
10
|
+
|
11
|
+
gemspec path: "../"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EncodedId
|
4
|
+
module Rails
|
5
|
+
# Configuration class for initializer
|
6
|
+
class Configuration
|
7
|
+
attr_accessor :salt,
|
8
|
+
:character_group_size,
|
9
|
+
:alphabet,
|
10
|
+
:id_length
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@character_group_size = 4
|
14
|
+
@alphabet = "0123456789abcdefghjkmnpqrstuvwxyz"
|
15
|
+
@id_length = 8
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
require "encoded_id"
|
5
|
+
|
6
|
+
module EncodedId
|
7
|
+
module Rails
|
8
|
+
module WithEncodedId
|
9
|
+
def self.included(base)
|
10
|
+
base.extend(ClassMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
# Find by encoded ID and optionally ensure record ID is the same as constraint (can be slugged)
|
15
|
+
def find_by_encoded_id(slugged_encoded_id, with_id: nil)
|
16
|
+
encoded_id = extract_id_part(slugged_encoded_id)
|
17
|
+
decoded_id = decode_encoded_id(encoded_id)
|
18
|
+
return nil if decoded_id.nil?
|
19
|
+
find_via_custom_id(decoded_id, :id, compare_to: with_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_by_encoded_id!(slugged_encoded_id, with_id: nil)
|
23
|
+
encoded_id = extract_id_part(slugged_encoded_id)
|
24
|
+
decoded_id = decode_encoded_id(encoded_id)
|
25
|
+
raise ActiveRecord::RecordNotFound if decoded_id.nil?
|
26
|
+
find_via_custom_id!(decoded_id, :id, compare_to: with_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Find by a fixed slug value (assumed as an attribute value in the DB)
|
30
|
+
def find_by_fixed_slug(slug, attribute: :slug, with_id: nil)
|
31
|
+
find_via_custom_id(slug, attribute, compare_to: with_id)
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_by_fixed_slug!(slug, attribute: :slug, with_id: nil)
|
35
|
+
find_via_custom_id!(slug, attribute, compare_to: with_id)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Find by record ID where the ID has been slugged
|
39
|
+
def find_by_slugged_id(slugged_id, with_id: nil)
|
40
|
+
id_part = decode_slugged_ids(slugged_id)
|
41
|
+
unless with_id.nil?
|
42
|
+
return unless with_id == id_part
|
43
|
+
end
|
44
|
+
where(id: id_part)&.first
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_by_slugged_id!(slugged_id, with_id: nil)
|
48
|
+
id_part = decode_slugged_ids(slugged_id)
|
49
|
+
unless with_id.nil?
|
50
|
+
raise ActiveRecord::RecordNotFound unless with_id == id_part
|
51
|
+
end
|
52
|
+
find(id_part)
|
53
|
+
end
|
54
|
+
|
55
|
+
# relation helpers
|
56
|
+
|
57
|
+
def where_encoded_id(slugged_encoded_id)
|
58
|
+
decoded_id = decode_encoded_id(extract_id_part(slugged_encoded_id))
|
59
|
+
raise ActiveRecord::RecordNotFound if decoded_id.nil?
|
60
|
+
where(id: decoded_id)
|
61
|
+
end
|
62
|
+
|
63
|
+
def where_fixed_slug(slug, attribute: :slug)
|
64
|
+
where(attribute => slug)
|
65
|
+
end
|
66
|
+
|
67
|
+
def where_slugged_id(slugged_id)
|
68
|
+
id_part = decode_slugged_ids(slugged_id)
|
69
|
+
raise ActiveRecord::RecordNotFound if id_part.nil?
|
70
|
+
where(id: id_part)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Encode helpers
|
74
|
+
|
75
|
+
def encode_encoded_id(id, options = {})
|
76
|
+
raise StandardError, "You must pass an ID" if id.blank?
|
77
|
+
hash_id_encoder(options).encode(id)
|
78
|
+
end
|
79
|
+
|
80
|
+
def encode_multi_encoded_id(encoded_ids, options = {})
|
81
|
+
raise ::StandardError, "You must pass IDs" if encoded_ids.blank?
|
82
|
+
hash_id_encoder(options).encode(encoded_ids)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Decode helpers
|
86
|
+
|
87
|
+
# Decode a encoded_id (can be slugged)
|
88
|
+
def decode_encoded_id(slugged_encoded_id, options = {})
|
89
|
+
internal_decode_encoded_id(slugged_encoded_id, options)&.first
|
90
|
+
end
|
91
|
+
|
92
|
+
def decode_multi_encoded_id(slugged_encoded_id, options = {})
|
93
|
+
internal_decode_encoded_id(slugged_encoded_id, options)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Decode a Slugged ID
|
97
|
+
def decode_slugged_id(slugged)
|
98
|
+
return if slugged.blank?
|
99
|
+
extract_id_part(slugged).to_i
|
100
|
+
end
|
101
|
+
|
102
|
+
# Decode a set of slugged IDs
|
103
|
+
def decode_slugged_ids(slugged)
|
104
|
+
return if slugged.blank?
|
105
|
+
extract_id_part(slugged).split("-").map(&:to_i)
|
106
|
+
end
|
107
|
+
|
108
|
+
# This can be overridden in the model to provide a custom salt
|
109
|
+
def encoded_id_salt
|
110
|
+
unless config && config.salt.present?
|
111
|
+
raise ::StandardError, "You must set a model specific encoded_id_salt or a gem wide one"
|
112
|
+
end
|
113
|
+
unless name.present?
|
114
|
+
raise ::StandardError, "The class must have a name to ensure encode id uniqueness. " \
|
115
|
+
"Please set a name on the class or override `encoded_id_salt`."
|
116
|
+
end
|
117
|
+
salt = config.salt
|
118
|
+
raise ::StandardError, "Encoded ID salt is invalid" if salt.blank? || salt.size < 4
|
119
|
+
"#{name}/#{salt}"
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def hash_id_encoder(options)
|
125
|
+
::EncodedId::ReversibleId.new(
|
126
|
+
salt: options[:salt].presence || encoded_id_salt,
|
127
|
+
length: options[:id_length] || config.id_length,
|
128
|
+
split_at: options[:character_group_size] || config.character_group_size,
|
129
|
+
alphabet: options[:alphabet] || config.alphabet
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
def config
|
134
|
+
::EncodedId::Rails.configuration
|
135
|
+
end
|
136
|
+
|
137
|
+
def internal_decode_encoded_id(slugged_encoded_id, options)
|
138
|
+
return if slugged_encoded_id.blank?
|
139
|
+
encoded_id = extract_id_part(slugged_encoded_id)
|
140
|
+
return if encoded_id.blank?
|
141
|
+
hash_id_encoder(options).decode(encoded_id)
|
142
|
+
rescue EncodedId::EncodedIdFormatError
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
|
146
|
+
def find_via_custom_id(value, attribute, compare_to: nil)
|
147
|
+
return if value.blank?
|
148
|
+
record = find_by({attribute => value})
|
149
|
+
return unless record
|
150
|
+
unless compare_to.nil?
|
151
|
+
return unless compare_to == record.send(attribute)
|
152
|
+
end
|
153
|
+
record
|
154
|
+
end
|
155
|
+
|
156
|
+
def find_via_custom_id!(value, attribute, compare_to: nil)
|
157
|
+
raise ::ActiveRecord::RecordNotFound if value.blank?
|
158
|
+
record = find_by!({attribute => value})
|
159
|
+
unless compare_to.nil?
|
160
|
+
raise ::ActiveRecord::RecordNotFound unless compare_to == record.send(attribute)
|
161
|
+
end
|
162
|
+
record
|
163
|
+
end
|
164
|
+
|
165
|
+
def extract_id_part(slugged_id)
|
166
|
+
return if slugged_id.blank?
|
167
|
+
has_slug = slugged_id.include?("--")
|
168
|
+
return slugged_id unless has_slug
|
169
|
+
split_slug = slugged_id.split("--")
|
170
|
+
split_slug.last if has_slug && split_slug.size > 1
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Instance methods
|
175
|
+
|
176
|
+
def encoded_id
|
177
|
+
@encoded_id ||= self.class.encode_encoded_id(id)
|
178
|
+
end
|
179
|
+
|
180
|
+
# (slug)--(hash id)
|
181
|
+
def slugged_encoded_id(with: :slug)
|
182
|
+
@slugged_encoded_id ||= generate_composite_id(with, :encoded_id)
|
183
|
+
end
|
184
|
+
|
185
|
+
# (name slug)--(record id(s) (separated by hyphen))
|
186
|
+
def slugged_id(with: :slug)
|
187
|
+
@slugged_id ||= generate_composite_id(with, :id)
|
188
|
+
end
|
189
|
+
|
190
|
+
# By default slug calls `name` if it exists or returns class name
|
191
|
+
def slug
|
192
|
+
klass = self.class.name&.underscore
|
193
|
+
return klass unless respond_to? :name
|
194
|
+
given_name = name
|
195
|
+
return given_name if given_name.present?
|
196
|
+
klass
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def generate_composite_id(name_method, id_method)
|
202
|
+
name_part = send(name_method)
|
203
|
+
id_part = send(id_method)
|
204
|
+
unless id_part.present? && name_part.present?
|
205
|
+
raise(::StandardError, "The model has no #{id_method} or #{name_method}")
|
206
|
+
end
|
207
|
+
"#{name_part.to_s.parameterize}--#{id_part}"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "rails/version"
|
4
|
+
require_relative "rails/configuration"
|
5
|
+
require_relative "rails/with_encoded_id"
|
6
|
+
|
7
|
+
module EncodedId
|
8
|
+
module Rails
|
9
|
+
# Configuration
|
10
|
+
class << self
|
11
|
+
attr_reader :configuration
|
12
|
+
|
13
|
+
def configure
|
14
|
+
@configuration ||= Configuration.new
|
15
|
+
yield(configuration) if block_given?
|
16
|
+
configuration
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Expose directly on EncodedId
|
22
|
+
WithEncodedId = Rails::WithEncodedId
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators/base"
|
4
|
+
|
5
|
+
module EncodedId
|
6
|
+
module Rails
|
7
|
+
module Generators
|
8
|
+
# The Install generator `encoded_id-rails:install`
|
9
|
+
class InstallGenerator < ::Rails::Generators::Base
|
10
|
+
source_root File.expand_path(__dir__)
|
11
|
+
|
12
|
+
desc "Creates an initializer for the gem."
|
13
|
+
def copy_tasks
|
14
|
+
template "templates/encoded_id.rb", "config/initializers/encoded_id.rb"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
EncodedId::Rails.configure do |config|
|
4
|
+
# The salt is used in the Hashids algorithm to generate the encoded ID. It ensures that the same ID will result in
|
5
|
+
# a different encoded ID. You must configure one and it must be longer that 4 characters. It can be configured on a
|
6
|
+
# model by model basis too.
|
7
|
+
#
|
8
|
+
# config.salt = "I2@2EBAw1lE#yvh4baf43k"
|
9
|
+
|
10
|
+
# The number of characters of the encoded ID that are grouped before the hyphen separator is inserted.
|
11
|
+
# `nil` disables grouping.
|
12
|
+
#
|
13
|
+
# nil -> abcdefghijklmnop
|
14
|
+
# 4 -> abcd-efgh-ijkl-mnop
|
15
|
+
# 8 -> abcdefgh-ijklmnop
|
16
|
+
#
|
17
|
+
# Default: 4
|
18
|
+
#
|
19
|
+
# config.character_group_size = 4
|
20
|
+
|
21
|
+
# The characters allowed in the encoded ID.
|
22
|
+
# Note, hash ids requires at least 16 unique alphabet characters.
|
23
|
+
#
|
24
|
+
# Default: a reduced character set Crockford alphabet and split groups, see https://www.crockford.com/wrmg/base32.html
|
25
|
+
#
|
26
|
+
# config.alphabet = "0123456789abcdefghjkmnpqrstuvwxyz"
|
27
|
+
|
28
|
+
# The minimum length of the encoded ID. Note that this is not a hard limit, the actual length may be longer as hash IDs
|
29
|
+
# may expand the length as needed to encode the full input. However encoded IDs will never be shorter than this.
|
30
|
+
#
|
31
|
+
# 4 -> "abcd"
|
32
|
+
# 8 -> "abcd-efgh" (with character_group_size = 4)
|
33
|
+
#
|
34
|
+
# Default: 8
|
35
|
+
#
|
36
|
+
# config.id_length = 8
|
37
|
+
end
|
data/rbs_collection.yaml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Download sources
|
2
|
+
sources:
|
3
|
+
- name: ruby/gem_rbs_collection
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
5
|
+
revision: main
|
6
|
+
repo_dir: gems
|
7
|
+
|
8
|
+
# A directory to install the downloaded RBSs
|
9
|
+
path: .gem_rbs_collection
|
10
|
+
|
11
|
+
gems:
|
12
|
+
- name: encoded_id-rails
|
13
|
+
ignore: true
|
14
|
+
# Skip loading rbs gem's RBS.
|
15
|
+
# It's unnecessary if you don't use rbs as a library.
|
16
|
+
- name: rbs
|
17
|
+
ignore: true
|
18
|
+
- name: rake
|
19
|
+
ignore: true
|
20
|
+
- name: minitest
|
21
|
+
ignore: true
|
22
|
+
- name: standard
|
23
|
+
ignore: true
|
24
|
+
- name: steep
|
25
|
+
ignore: true
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module EncodedId
|
2
|
+
module Rails
|
3
|
+
# See the writing guide of rbs: https://github.com/ruby/rbs#guides
|
4
|
+
|
5
|
+
class Configuration
|
6
|
+
attr_accessor salt: ::String
|
7
|
+
|
8
|
+
attr_accessor character_group_size: ::Integer
|
9
|
+
|
10
|
+
attr_accessor alphabet: ::String
|
11
|
+
|
12
|
+
attr_accessor id_length: ::Integer
|
13
|
+
|
14
|
+
def initialize: () -> void
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader self.configuration: Configuration
|
18
|
+
|
19
|
+
def self.configure: () { (Configuration config) -> void } -> void
|
20
|
+
|
21
|
+
module WithEncodedId
|
22
|
+
# Find by encoded ID and optionally ensure record ID is the same as constraint (can be slugged)
|
23
|
+
def self.find_by_encoded_id: (::String slugged_encoded_id, ?with_id: ::Symbol?) -> (nil | untyped)
|
24
|
+
|
25
|
+
def self.find_by_encoded_id!: (::String slugged_encoded_id, ?with_id: ::Symbol?) -> untyped
|
26
|
+
|
27
|
+
# Find by a fixed slug value (assumed as an attribute value in the DB)
|
28
|
+
def self.find_by_fixed_slug: (::String slug, ?attribute: ::Symbol, ?with_id: ::Symbol?) -> (nil | untyped)
|
29
|
+
|
30
|
+
def self.find_by_fixed_slug!: (::String slug, ?attribute: ::Symbol, ?with_id: ::Symbol?) -> untyped
|
31
|
+
|
32
|
+
# Find by record ID where the ID has been slugged
|
33
|
+
def self.find_by_slugged_id: (::String slugged_id, ?with_id: ::Symbol?) -> (nil | untyped)
|
34
|
+
|
35
|
+
def self.find_by_slugged_id!: (::String slugged_id, ?with_id: ::Symbol?) -> untyped
|
36
|
+
|
37
|
+
def self.where_encoded_id: (::String slugged_encoded_id) -> untyped
|
38
|
+
|
39
|
+
def self.where_fixed_slug: (::String slug, ?attribute: ::Symbol) -> untyped
|
40
|
+
|
41
|
+
def self.where_slugged_id: (::String slugged_id) -> untyped
|
42
|
+
|
43
|
+
def self.encode_encoded_id: (untyped id, ?::Hash[::Symbol, untyped] options) -> ::String
|
44
|
+
|
45
|
+
def self.encode_multi_encoded_id: (::Array[untyped] encoded_ids, ?::Hash[::Symbol, untyped] options) -> ::String
|
46
|
+
|
47
|
+
# Decode a encoded_id (can be slugged)
|
48
|
+
def self.decode_encoded_id: (::String slugged_encoded_id, ?::Hash[::Symbol, untyped] options) -> (nil | ::Integer)
|
49
|
+
|
50
|
+
def self.decode_multi_encoded_id: (::String slugged_encoded_id, ?::Hash[::Symbol, untyped] options) -> (nil | Array[::Integer])
|
51
|
+
|
52
|
+
# Decode a Slugged ID
|
53
|
+
def self.decode_slugged_id: (::String slugged) -> (nil | ::Integer)
|
54
|
+
|
55
|
+
# Decode a set of slugged IDs
|
56
|
+
def self.decode_slugged_ids: (::String slugged) -> (nil | Array[::Integer])
|
57
|
+
|
58
|
+
# This can be overridden in the model to provide a custom salt
|
59
|
+
def self.encoded_id_salt: () -> ::String
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def self.hash_id_encoder: (untyped options) -> untyped
|
64
|
+
|
65
|
+
def self.config: () -> untyped
|
66
|
+
|
67
|
+
@slugged_id: ::String
|
68
|
+
@encoded_id: ::String
|
69
|
+
@slugged_encoded_id: ::String
|
70
|
+
|
71
|
+
def encoded_id: () -> untyped
|
72
|
+
|
73
|
+
# (slug)--(hash id)
|
74
|
+
def slugged_encoded_id: (?with: ::Symbol) -> untyped
|
75
|
+
|
76
|
+
# (name slug)--(record id(s) (separated by hyphen))
|
77
|
+
def slugged_id: (?with: ::Symbol) -> untyped
|
78
|
+
|
79
|
+
# By default slug calls `name` if it exists or returns class name
|
80
|
+
def slug: () -> untyped
|
81
|
+
|
82
|
+
def self.internal_decode_encoded_id: (untyped slugged_encoded_id, untyped options) -> (nil | untyped)
|
83
|
+
|
84
|
+
def self.find_via_custom_id: (untyped value, untyped attribute, ?compare_to: untyped?) -> (nil | untyped)
|
85
|
+
|
86
|
+
def self.find_via_custom_id!: (untyped value, untyped attribute, ?compare_to: untyped?) -> untyped
|
87
|
+
|
88
|
+
def self.extract_id_part: (untyped slugged_id) -> (nil | untyped)
|
89
|
+
|
90
|
+
def generate_composite_id: (untyped name_method, untyped id_method) -> ::String
|
91
|
+
|
92
|
+
# Methods defined on AR
|
93
|
+
def self.where: (*untyped) -> untyped
|
94
|
+
|
95
|
+
def self.find: (*untyped) -> (nil | untyped)
|
96
|
+
|
97
|
+
def self.find!: (*untyped) -> untyped
|
98
|
+
|
99
|
+
def self.find_by: (*untyped) -> (nil | untyped)
|
100
|
+
|
101
|
+
def self.find_by!: (*untyped) -> untyped
|
102
|
+
|
103
|
+
# FIXME: To make type check happy, but may not exist!
|
104
|
+
# We call if respond_to? but type checker doesn't know that
|
105
|
+
def name: () -> ::String
|
106
|
+
def id: () -> ::String
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: encoded_id-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Ierodiaconou
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-11-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.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'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '6.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '6.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: encoded_id
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.3'
|
55
|
+
description: Write a longer description or delete this line.
|
56
|
+
email:
|
57
|
+
- stevegeek@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".standard.yml"
|
63
|
+
- CHANGELOG.md
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- Steepfile
|
69
|
+
- gemfiles/rails_6.0.gemfile
|
70
|
+
- gemfiles/rails_7.0.gemfile
|
71
|
+
- lib/encoded_id/rails.rb
|
72
|
+
- lib/encoded_id/rails/configuration.rb
|
73
|
+
- lib/encoded_id/rails/version.rb
|
74
|
+
- lib/encoded_id/rails/with_encoded_id.rb
|
75
|
+
- lib/generators/encoded_id/rails/USAGE
|
76
|
+
- lib/generators/encoded_id/rails/install_generator.rb
|
77
|
+
- lib/generators/encoded_id/rails/templates/encoded_id.rb
|
78
|
+
- rbs_collection.yaml
|
79
|
+
- sig/encoded_id/rails.rbs
|
80
|
+
homepage: https://github.com/stevegeek/encoded_id-rails
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata:
|
84
|
+
homepage_uri: https://github.com/stevegeek/encoded_id-rails
|
85
|
+
source_code_uri: https://github.com/stevegeek/encoded_id-rails
|
86
|
+
changelog_uri: https://github.com/stevegeek/encoded_id-rails/blob/master/CHANGELOG.md
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 2.6.0
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubygems_version: 3.3.7
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: Use EncodedIds with ActiveRecord models
|
106
|
+
test_files: []
|