sqids-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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +113 -0
- data/Rakefile +8 -0
- data/app/assets/config/sqids_rails_manifest.js +0 -0
- data/app/models/user.rb +6 -0
- data/db/migrate/20240705145551_create_users.rb +9 -0
- data/lib/sqids/rails/engine.rb +6 -0
- data/lib/sqids/rails/model.rb +107 -0
- data/lib/sqids/rails/version.rb +5 -0
- data/lib/sqids/rails.rb +23 -0
- data/lib/sqids-rails.rb +1 -0
- data/lib/tasks/sqids/rails_tasks.rake +4 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2806a56ec74df13fa5efa5f6ed2800d792223c7240b65cfad3cb50eff7a02a4b
|
4
|
+
data.tar.gz: 9f11f7fc06b94e888187ce01c5983431ae597761157652f9677f5c06e1be35d5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8b18b3d1ef47868206df30a4f89078464d65254e1494798d7724aade26d3d8a71bf7f15d9353bda313659f4401d246cde365895224713b34b09e092a133e5804
|
7
|
+
data.tar.gz: 9f184450853b55deff34b120e16fbacad516806f1c03bc7a8f88655ffb7dde094f0c68afdfaf02a18ef0c9bb20d6d2d1b483ec4e1bc9de2dc3b5654f2e8cc978
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 Tony Burns
|
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,113 @@
|
|
1
|
+
# sqids-rails
|
2
|
+
|
3
|
+
[Sqids](https://sqids.org) (formerly [Hashids](https://github.com/hashids)) integration for [Ruby on Rails](https://rubyonrails.org).
|
4
|
+
|
5
|
+
From [sqids-ruby](https://github.com/sqids/sqids-ruby):
|
6
|
+
|
7
|
+
> [Sqids](https://sqids.org/ruby) _(pronounced "squids")_ is a small library that lets you generate unique IDs from numbers. It's good for link shortening, fast & URL-safe ID generation and decoding back into numbers for quicker database lookups.
|
8
|
+
>
|
9
|
+
> Features:
|
10
|
+
>
|
11
|
+
> - Encode multiple numbers - generate short IDs from one or several non-negative numbers
|
12
|
+
> - Quick decoding - easily decode IDs back into numbers
|
13
|
+
> - Unique IDs - generate unique IDs by shuffling the alphabet once
|
14
|
+
> - ID padding - provide minimum length to make IDs more uniform
|
15
|
+
> - URL safe - auto-generated IDs do not contain common profanity
|
16
|
+
> - Randomized output - Sequential input provides nonconsecutive IDs
|
17
|
+
> - Many implementations - Support for 40+ programming languages
|
18
|
+
|
19
|
+
## Getting started
|
20
|
+
|
21
|
+
Run `bundle add sqids-rails` or add this line to your application's `Gemfile`:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'sqids-rails'
|
25
|
+
```
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
```shell
|
30
|
+
bundle
|
31
|
+
```
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
Add auto-generated sqids columns to your ActiveRecord models with `has_sqid`:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# Schema: users(sqid:string, long_sqid:string)
|
39
|
+
class User < ApplicationRecord
|
40
|
+
include Sqids::Rails::Model
|
41
|
+
|
42
|
+
has_sqid
|
43
|
+
has_sqid :long_sqid, min_length: 24
|
44
|
+
end
|
45
|
+
|
46
|
+
user = User.new
|
47
|
+
user.save
|
48
|
+
user.sqid # => "lzNKgEb6ZuaU"
|
49
|
+
user.sqid_long # => "4y3SVm9M2aV8Olu6p4zZoGij"
|
50
|
+
user.regenerate_sqid
|
51
|
+
user.regenerate_long_sqid
|
52
|
+
```
|
53
|
+
|
54
|
+
`has_sqid` follows the same behavior as ActiveRecord's built-in [has_secure_token](https://api.rubyonrails.org/classes/ActiveRecord/SecureToken/ClassMethods.html#method-i-has_secure_token)
|
55
|
+
|
56
|
+
Use a custom attribute name (the default is `sqid`):
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
has_sqid :uid
|
60
|
+
```
|
61
|
+
|
62
|
+
Enforce a _minimum length_ for generated IDs:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
has_sqid min_length: 24
|
66
|
+
```
|
67
|
+
|
68
|
+
Provide a custom alphabet for generated IDs:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
has_sqid alphabet: "FxnXM1kBN6cuhsAvjW3Co7l2RePyY8DwaU04Tzt9fHQrqSVKdpimLGIJOgb5ZE"
|
72
|
+
```
|
73
|
+
|
74
|
+
Prevent specific words from appearing anywhere in generated IDs:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
has_sqid blocklist: Set.new(%w[86Rf07])
|
78
|
+
```
|
79
|
+
|
80
|
+
## Roadmap
|
81
|
+
|
82
|
+
- [x] `has_sqid` for auto-generating Sqid columns
|
83
|
+
- [ ] Extensions to [ActiveRecord::FinderMethods](https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html) and [ActiveRecord::Associations::CollectionProxy](https://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-find) to find records with a Sqid-encoded primary key
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
Bug reports and pull requests are welcome on [GitHub](https://github.com/tbhb/sqids-rails). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/tbhb/sqids-rails/blob/main/CODE_OF_CONDUCT.md).
|
88
|
+
|
89
|
+
## Acknowledgements
|
90
|
+
|
91
|
+
Thanks to Ivan Akimov ([@4kimov](https://github.com/4kimov)) for creating and maintaining Sqids and [sqids-ruby](https://github.com/sqids/sqids-ruby), and Roberto Miranda ([@robertomiranda](https://github.com/robertomiranda)) for `has_secure_token`.
|
92
|
+
|
93
|
+
## MIT License
|
94
|
+
|
95
|
+
Copyright (c) 2024 Anthony Burns
|
96
|
+
|
97
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
98
|
+
of this software and associated documentation files (the "Software"), to deal
|
99
|
+
in the Software without restriction, including without limitation the rights
|
100
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
101
|
+
copies of the Software, and to permit persons to whom the Software is
|
102
|
+
furnished to do so, subject to the following conditions:
|
103
|
+
|
104
|
+
The above copyright notice and this permission notice shall be included in
|
105
|
+
all copies or substantial portions of the Software.
|
106
|
+
|
107
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
108
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
109
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
110
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
111
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
112
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
113
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
File without changes
|
data/app/models/user.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
class Sqids
|
2
|
+
module Rails
|
3
|
+
module Model
|
4
|
+
class AlphabetError < StandardError; end
|
5
|
+
|
6
|
+
class MinimumLengthError < StandardError; end
|
7
|
+
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Example using #has_sqid:
|
12
|
+
#
|
13
|
+
# # Schema: User(sqid:string, long_sqid:string)
|
14
|
+
# class User < ApplicationRecord
|
15
|
+
# include Sqids::Rails::Model
|
16
|
+
#
|
17
|
+
# has_sqid
|
18
|
+
# has_sqid :long_sqid, min_length: 24
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# user = User.new
|
22
|
+
# user.save
|
23
|
+
# user.sqid # => "lzNKgEb6ZuaU"
|
24
|
+
# user.sqid_long # => "4y3SVm9M2aV8Olu6p4zZoGij"
|
25
|
+
# user.regenerate_sqid
|
26
|
+
# user.regenerate_long_sqid
|
27
|
+
#
|
28
|
+
# +SecureRandom.random_number(Sqids.max_value)+ is used to generate the random number to encode.
|
29
|
+
#
|
30
|
+
# Note that it's still possible to generate a race condition in the database in the same way that
|
31
|
+
# {validates_uniqueness_of}[https://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_uniqueness_of]
|
32
|
+
# can. You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
|
33
|
+
#
|
34
|
+
# See the {Sqids Ruby}[https://github.com/sqids/sqids-ruby] documentation for more information on the options.
|
35
|
+
#
|
36
|
+
# === Options
|
37
|
+
#
|
38
|
+
# [:alphabet]
|
39
|
+
# The alphabet to use for encoding. Default is +Sqids::Rails.alphabet+.
|
40
|
+
# The minimum alphabet length is 3 characters.
|
41
|
+
# The alphabet cannot contain any multibyte characters.
|
42
|
+
#
|
43
|
+
# [:blocklist]
|
44
|
+
# The blocklist to use for encoding. Default is +Sqids::Rails.blocklist+.
|
45
|
+
#
|
46
|
+
# [:min_length]
|
47
|
+
# The minimum length of the generated sqid, from 0-255. Default is +Sqids::Rails.min_length+. Sqids cannot
|
48
|
+
# generate IDs up to a certain length, only at least a certain length.
|
49
|
+
#
|
50
|
+
# [:on]
|
51
|
+
# The callback when the value is generated. When called with <tt>on: :initialize</tt>, the value is generated
|
52
|
+
# in an <tt>after_initialize</tt> callback, otherwise the value will be used in a <tt>before_</tt> callback.
|
53
|
+
# When not specified, +:on+ will use the value of <tt>Sqids::Rails.generate_sqid_on</tt>, which defaults to
|
54
|
+
# +:initialize+.
|
55
|
+
def has_sqid(
|
56
|
+
attribute = :sqid,
|
57
|
+
alphabet: Sqids::Rails.alphabet,
|
58
|
+
blocklist: Sqids::Rails.blocklist,
|
59
|
+
min_length: Sqids::Rails.min_length,
|
60
|
+
on: Sqids::Rails.generate_sqid_on
|
61
|
+
)
|
62
|
+
if alphabet.length < 3
|
63
|
+
raise AlphabetError, "Sqid requires an alphabet of at least 3 characters"
|
64
|
+
end
|
65
|
+
|
66
|
+
if alphabet.each_char.any? { |char| char.bytesize > 1 }
|
67
|
+
raise AlphabetError, "Sqid alphabet cannot contain multibyte characters"
|
68
|
+
end
|
69
|
+
|
70
|
+
if alphabet.chars.uniq.length != alphabet.length
|
71
|
+
raise AlphabetError, "Sqid alphabet must contain unique characters"
|
72
|
+
end
|
73
|
+
|
74
|
+
if min_length < 0 || min_length > 255
|
75
|
+
raise MinimumLengthError, "Sqid requires a minimum length between 0 and 255 characters"
|
76
|
+
end
|
77
|
+
|
78
|
+
define_method(:"regenerate_#{attribute}") do
|
79
|
+
update!(
|
80
|
+
attribute => self.class.generate_unique_sqid(
|
81
|
+
alphabet: alphabet, blocklist: blocklist, min_length: min_length
|
82
|
+
)
|
83
|
+
)
|
84
|
+
end
|
85
|
+
set_callback(on, (on == :initialize) ? :after : :before) do
|
86
|
+
if new_record? && !query_attribute(attribute)
|
87
|
+
send(
|
88
|
+
:"#{attribute}=",
|
89
|
+
self.class.generate_unique_sqid(alphabet: alphabet, blocklist: blocklist, min_length: min_length)
|
90
|
+
)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def generate_unique_sqid(
|
96
|
+
alphabet: Sqids::Rails.alphabet, blocklist: Sqids::Rails.blocklist, min_length: Sqids::Rails.min_length
|
97
|
+
)
|
98
|
+
@sqids ||= {}
|
99
|
+
@sqids[[alphabet, blocklist, min_length]] ||= Sqids.new(
|
100
|
+
alphabet: alphabet, blocklist: blocklist, min_length: min_length
|
101
|
+
)
|
102
|
+
@sqids[[alphabet, blocklist, min_length]].encode([SecureRandom.random_number(Sqids.max_value)])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/lib/sqids/rails.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "active_support/core_ext/module/attribute_accessors"
|
2
|
+
|
3
|
+
require "sqids"
|
4
|
+
require "sqids/rails/version"
|
5
|
+
require "sqids/rails/engine"
|
6
|
+
require "sqids/rails/model"
|
7
|
+
|
8
|
+
class Sqids
|
9
|
+
module Rails
|
10
|
+
mattr_accessor :alphabet, default: Sqids::DEFAULT_ALPHABET
|
11
|
+
mattr_accessor :blocklist, default: Sqids::DEFAULT_BLOCKLIST
|
12
|
+
mattr_accessor :min_length, default: Sqids::DEFAULT_MIN_LENGTH
|
13
|
+
mattr_accessor :generate_sqid_on, default: :initialize
|
14
|
+
|
15
|
+
def self.configure
|
16
|
+
yield self
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.sqids
|
20
|
+
@sqids ||= Sqids.new(alphabet: alphabet, blocklist: blocklist, min_length: min_length)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/sqids-rails.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "sqids/rails"
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqids-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tony Burns
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.1.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.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqids
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: appraisal
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Short, unique, and human-readable IDs for ActiveRecord models with Sqids.
|
56
|
+
email:
|
57
|
+
- tony@tonyburns.net
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- LICENSE.txt
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- app/assets/config/sqids_rails_manifest.js
|
66
|
+
- app/models/user.rb
|
67
|
+
- db/migrate/20240705145551_create_users.rb
|
68
|
+
- lib/sqids-rails.rb
|
69
|
+
- lib/sqids/rails.rb
|
70
|
+
- lib/sqids/rails/engine.rb
|
71
|
+
- lib/sqids/rails/model.rb
|
72
|
+
- lib/sqids/rails/version.rb
|
73
|
+
- lib/tasks/sqids/rails_tasks.rake
|
74
|
+
homepage: https://github.com/tbhb/sqids-rails
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata:
|
78
|
+
homepage_uri: https://github.com/tbhb/sqids-rails
|
79
|
+
source_code_uri: https://github.com/tbhb/sqids-rails
|
80
|
+
changelog_uri: https://github.com/tbhb/sqids-rails/blob/main/sqids-rails/CHANGELOG.md
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.1'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubygems_version: 3.5.14
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: Short, unique, and human-readable IDs for ActiveRecord models with Sqids.
|
100
|
+
test_files: []
|