rails_type_id 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/.rubocop.yml +25 -0
- data/.ruby-version +1 -0
- data/README.md +46 -0
- data/Rakefile +16 -0
- data/lib/rails_type_id/concern.rb +129 -0
- data/lib/rails_type_id/require.rb +6 -0
- data/lib/rails_type_id/test_helper.rb +16 -0
- data/lib/rails_type_id/version.rb +6 -0
- data/lib/rails_type_id.rb +9 -0
- data/lib/tapioca/dsl/compilers/rails_type_id_compiler.rb +49 -0
- data/sig/rails_type_id.rbs +4 -0
- data/sorbet/config +4 -0
- data/sorbet/rbi/annotations/.gitattributes +1 -0
- data/sorbet/rbi/annotations/actionmailer.rbi +10 -0
- data/sorbet/rbi/annotations/actionpack.rbi +430 -0
- data/sorbet/rbi/annotations/actionview.rbi +75 -0
- data/sorbet/rbi/annotations/activejob.rbi +44 -0
- data/sorbet/rbi/annotations/activemodel.rbi +89 -0
- data/sorbet/rbi/annotations/activerecord.rbi +98 -0
- data/sorbet/rbi/annotations/activesupport.rbi +468 -0
- data/sorbet/rbi/annotations/globalid.rbi +30 -0
- data/sorbet/rbi/annotations/minitest.rbi +119 -0
- data/sorbet/rbi/annotations/railties.rbi +61 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/dsl/.gitattributes +1 -0
- data/sorbet/rbi/dsl/active_model/validations/callbacks.rbi +21 -0
- data/sorbet/rbi/dsl/active_model/validations.rbi +26 -0
- data/sorbet/rbi/dsl/active_support/callbacks.rbi +21 -0
- data/sorbet/rbi/dsl/rails_type_id/concern.rbi +22 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/actioncable@8.0.2.rbi +3133 -0
- data/sorbet/rbi/gems/actionmailbox@8.0.2.rbi +991 -0
- data/sorbet/rbi/gems/actionmailer@8.0.2.rbi +2775 -0
- data/sorbet/rbi/gems/actionpack@8.0.2.rbi +21167 -0
- data/sorbet/rbi/gems/actiontext@8.0.2.rbi +1449 -0
- data/sorbet/rbi/gems/actionview@8.0.2.rbi +15789 -0
- data/sorbet/rbi/gems/activejob@8.0.2.rbi +2864 -0
- data/sorbet/rbi/gems/activemodel@8.0.2.rbi +6946 -0
- data/sorbet/rbi/gems/activerecord@8.0.2.rbi +42458 -0
- data/sorbet/rbi/gems/activestorage@8.0.2.rbi +2156 -0
- data/sorbet/rbi/gems/activesupport@8.0.2.rbi +21274 -0
- data/sorbet/rbi/gems/ast@2.4.3.rbi +586 -0
- data/sorbet/rbi/gems/base64@0.3.0.rbi +545 -0
- data/sorbet/rbi/gems/benchmark@0.4.1.rbi +619 -0
- data/sorbet/rbi/gems/bigdecimal@3.2.2.rbi +275 -0
- data/sorbet/rbi/gems/builder@3.3.0.rbi +9 -0
- data/sorbet/rbi/gems/concurrent-ruby@1.3.5.rbi +11734 -0
- data/sorbet/rbi/gems/connection_pool@2.5.3.rbi +9 -0
- data/sorbet/rbi/gems/crass@1.0.6.rbi +623 -0
- data/sorbet/rbi/gems/date@3.4.1.rbi +403 -0
- data/sorbet/rbi/gems/drb@2.2.3.rbi +1661 -0
- data/sorbet/rbi/gems/erb@5.0.2.rbi +878 -0
- data/sorbet/rbi/gems/erubi@1.13.1.rbi +157 -0
- data/sorbet/rbi/gems/globalid@1.2.1.rbi +742 -0
- data/sorbet/rbi/gems/i18n@1.14.7.rbi +2383 -0
- data/sorbet/rbi/gems/io-console@0.8.1.rbi +9 -0
- data/sorbet/rbi/gems/json@2.12.2.rbi +2287 -0
- data/sorbet/rbi/gems/language_server-protocol@3.17.0.5.rbi +9 -0
- data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +323 -0
- data/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
- data/sorbet/rbi/gems/loofah@2.24.1.rbi +1105 -0
- data/sorbet/rbi/gems/mail@2.8.1.rbi +8890 -0
- data/sorbet/rbi/gems/marcel@1.0.4.rbi +239 -0
- data/sorbet/rbi/gems/mini_mime@1.1.5.rbi +173 -0
- data/sorbet/rbi/gems/minitest@5.25.5.rbi +2231 -0
- data/sorbet/rbi/gems/net-imap@0.5.9.rbi +10285 -0
- data/sorbet/rbi/gems/net-pop@0.1.2.rbi +927 -0
- data/sorbet/rbi/gems/net-protocol@0.2.2.rbi +292 -0
- data/sorbet/rbi/gems/net-smtp@0.5.1.rbi +1240 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +177 -0
- data/sorbet/rbi/gems/nio4r@2.7.4.rbi +388 -0
- data/sorbet/rbi/gems/nokogiri@1.18.9.rbi +8548 -0
- data/sorbet/rbi/gems/parallel@1.27.0.rbi +291 -0
- data/sorbet/rbi/gems/parser@3.3.9.0.rbi +5537 -0
- data/sorbet/rbi/gems/pp@0.6.2.rbi +368 -0
- data/sorbet/rbi/gems/prettyprint@0.2.0.rbi +477 -0
- data/sorbet/rbi/gems/prism@1.4.0.rbi +41790 -0
- data/sorbet/rbi/gems/psych@5.2.6.rbi +2542 -0
- data/sorbet/rbi/gems/racc@1.8.1.rbi +168 -0
- data/sorbet/rbi/gems/rack-session@2.1.1.rbi +722 -0
- data/sorbet/rbi/gems/rack-test@2.2.0.rbi +729 -0
- data/sorbet/rbi/gems/rack@3.2.0.rbi +5054 -0
- data/sorbet/rbi/gems/rackup@2.2.1.rbi +230 -0
- data/sorbet/rbi/gems/rails-dom-testing@2.3.0.rbi +790 -0
- data/sorbet/rbi/gems/rails-html-sanitizer@1.6.2.rbi +645 -0
- data/sorbet/rbi/gems/rails@8.0.2.rbi +9 -0
- data/sorbet/rbi/gems/railties@8.0.2.rbi +4014 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
- data/sorbet/rbi/gems/rake@13.3.0.rbi +3039 -0
- data/sorbet/rbi/gems/rbi@0.3.6.rbi +5162 -0
- data/sorbet/rbi/gems/rbs@4.0.0.dev.4.rbi +7895 -0
- data/sorbet/rbi/gems/rdoc@6.14.2.rbi +12944 -0
- data/sorbet/rbi/gems/regexp_parser@2.10.0.rbi +3833 -0
- data/sorbet/rbi/gems/reline@0.6.2.rbi +9 -0
- data/sorbet/rbi/gems/require-hooks@0.2.2.rbi +110 -0
- data/sorbet/rbi/gems/rexml@3.4.1.rbi +5205 -0
- data/sorbet/rbi/gems/rubocop-ast@1.46.0.rbi +7473 -0
- data/sorbet/rbi/gems/rubocop-sorbet@0.10.5.rbi +2386 -0
- data/sorbet/rbi/gems/rubocop@1.79.1.rbi +63674 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
- data/sorbet/rbi/gems/securerandom@0.4.1.rbi +75 -0
- data/sorbet/rbi/gems/spoom@1.7.5.rbi +5832 -0
- data/sorbet/rbi/gems/sqlite3@2.7.3.rbi +1989 -0
- data/sorbet/rbi/gems/stringio@3.1.7.rbi +9 -0
- data/sorbet/rbi/gems/tapioca@0.17.7.rbi +3692 -0
- data/sorbet/rbi/gems/thor@1.4.0.rbi +4399 -0
- data/sorbet/rbi/gems/timeout@0.4.3.rbi +157 -0
- data/sorbet/rbi/gems/typeid@0.2.2.rbi +239 -0
- data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +5919 -0
- data/sorbet/rbi/gems/unicode-display_width@3.1.4.rbi +132 -0
- data/sorbet/rbi/gems/unicode-emoji@4.0.4.rbi +251 -0
- data/sorbet/rbi/gems/uri@1.0.3.rbi +2354 -0
- data/sorbet/rbi/gems/useragent@0.16.11.rbi +9 -0
- data/sorbet/rbi/gems/uuid7@0.2.0.rbi +60 -0
- data/sorbet/rbi/gems/websocket-driver@0.8.0.rbi +1065 -0
- data/sorbet/rbi/gems/websocket-extensions@0.1.5.rbi +117 -0
- data/sorbet/rbi/gems/with_model@2.2.0.rbi +282 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +430 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +18512 -0
- data/sorbet/rbi/gems/zeitwerk@2.7.3.rbi +1196 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +13 -0
- metadata +208 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b002a4e9136bfe9b886e13b8aaea8962f98b6ccf94e64dc875423c985fab6f8c
|
4
|
+
data.tar.gz: 7e245dcb3726845ddc8617cb91f2b6e79510baff72348d27124255855d79b3e6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eb7fb1c5a1953d4b6ce56aa3771b18001220bcb383413abf17157d4cd7644cc505ac6c8cefe30902d246cf15b297fffa631db674ef33a07852c9189d3a08ac19
|
7
|
+
data.tar.gz: d534f95fbbec9934890497da6b2c9b0a4e0d82189b66c8e176a57758d5c9353336147b6136343b1cd8ee18388be655b631d336452e9a0fd5528b8dd9100178df
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
plugins:
|
2
|
+
- rubocop-sorbet
|
3
|
+
|
4
|
+
AllCops:
|
5
|
+
Enabled: true
|
6
|
+
NewCops: enable
|
7
|
+
TargetRubyVersion: 3.1
|
8
|
+
Exclude:
|
9
|
+
- 'vendor/**/*'
|
10
|
+
|
11
|
+
Metrics/AbcSize:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
Metrics/MethodLength:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
Sorbet/HasSigil:
|
18
|
+
Enabled: true
|
19
|
+
MinimumStrictness: true
|
20
|
+
|
21
|
+
Style/StringLiterals:
|
22
|
+
EnforcedStyle: double_quotes
|
23
|
+
|
24
|
+
Style/StringLiteralsInInterpolation:
|
25
|
+
EnforcedStyle: double_quotes
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.4.5
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# rails_type_id
|
2
|
+
|
3
|
+
A gem that makes simple to use [TypeID](https://github.com/broothie/typeid-ruby) as the primary key for ActiveRecord models.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the gem and add to the application's Gemfile by executing:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
bundle add rails_type_id
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
### Declaring on models
|
16
|
+
Add `RailsTypeId::Concern` to the model. This model's `id` field should have either a String or UUID database column type.
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
# app/models/my_model.rb
|
20
|
+
require "rails_type_id"
|
21
|
+
|
22
|
+
class MyModel < ActiveRecord::Base
|
23
|
+
include RailsTypeId::Concern
|
24
|
+
|
25
|
+
# Prefix should be unique within your project
|
26
|
+
with_type_id_prefix("mm")
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
### Using the `type_id` field
|
31
|
+
|
32
|
+
Model instances will have a `type_id` field of type `TypeID`.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
my_model = MyModel.create!(..)
|
36
|
+
my_model.id #=> "019867fe-560f-7941-a7ed-8472639c7ace"
|
37
|
+
my_model.type_id #=> #<TypeID mm_01k1kzwngff50tfvc4e9hsrype>
|
38
|
+
my_model.type_id.to_s #=> mm_01k1kzwngff50tfvc4e9hsrype
|
39
|
+
```
|
40
|
+
|
41
|
+
## Development
|
42
|
+
|
43
|
+
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.
|
44
|
+
|
45
|
+
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).
|
46
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "minitest/test_task"
|
5
|
+
|
6
|
+
Minitest::TestTask.create
|
7
|
+
|
8
|
+
require "rubocop/rake_task"
|
9
|
+
|
10
|
+
RuboCop::RakeTask.new
|
11
|
+
|
12
|
+
task :sorbet do
|
13
|
+
sh "bin/srb"
|
14
|
+
end
|
15
|
+
|
16
|
+
task default: %i[test rubocop sorbet]
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# typed: false # rubocop:disable Sorbet/HasSigil
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "active_model"
|
5
|
+
require "active_support"
|
6
|
+
require "sorbet-runtime"
|
7
|
+
require "typeid"
|
8
|
+
|
9
|
+
module RailsTypeId
|
10
|
+
# RailsTypeId::Concern is a Rails ActiveSupport::Concern that uses a Stripe-style "type ID"
|
11
|
+
# for its ID field.
|
12
|
+
module Concern
|
13
|
+
extend ::ActiveSupport::Concern
|
14
|
+
include ::ActiveModel::Validations::Callbacks
|
15
|
+
|
16
|
+
class InvalidTypeIdPrefix < StandardError; end
|
17
|
+
|
18
|
+
# Checks validity of the ActiveRecord model instances
|
19
|
+
class Validator < ActiveModel::Validator
|
20
|
+
def validate(record)
|
21
|
+
result = Helpers.validate_type_id_prefix(record.class.type_id_prefix)
|
22
|
+
record.errors.add(:type_id_prefix, result) if result
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class_methods do
|
27
|
+
def with_type_id_prefix(prefix)
|
28
|
+
Helpers.validate_type_id_prefix!(prefix)
|
29
|
+
|
30
|
+
@_type_id_prefix = prefix
|
31
|
+
end
|
32
|
+
|
33
|
+
def type_id_prefix
|
34
|
+
@_type_id_prefix
|
35
|
+
end
|
36
|
+
|
37
|
+
def from_controller_id_param(type_id_str)
|
38
|
+
find(TypeID.from_string(type_id_str).uuid.to_s)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
included do
|
43
|
+
attribute :id # Postgres UUID field
|
44
|
+
|
45
|
+
before_create :generate_uuid_v7
|
46
|
+
validates_with Validator
|
47
|
+
|
48
|
+
# Returns the TypeID for the model
|
49
|
+
# @return [TypeID]
|
50
|
+
define_method :type_id do
|
51
|
+
Helpers.validate_type_id_prefix!(self.class.type_id_prefix)
|
52
|
+
TypeID.from_uuid(self.class.type_id_prefix, id)
|
53
|
+
end
|
54
|
+
|
55
|
+
# If `id` is unset, generates a new UUID v7 and sets it
|
56
|
+
# @return [void]
|
57
|
+
define_method :generate_uuid_v7 do
|
58
|
+
case self.class.attribute_types["id"].type
|
59
|
+
when :uuid, :string
|
60
|
+
self.id ||= SecureRandom.uuid_v7
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
define_method :to_param do
|
65
|
+
type_id.to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Internal helper methods
|
70
|
+
class Helpers
|
71
|
+
extend T::Sig
|
72
|
+
|
73
|
+
class << self
|
74
|
+
def validate_type_id_prefix(prefix)
|
75
|
+
return "type_id_prefix cannot be nil" if prefix.nil?
|
76
|
+
|
77
|
+
return nil if prefix.match(/\A[a-z]{1,10}\z/)
|
78
|
+
|
79
|
+
"type_id_prefix must be lowercase alphabetic (a-z) with length >= 1, <= 10"
|
80
|
+
end
|
81
|
+
|
82
|
+
def validate_type_id_prefix!(prefix)
|
83
|
+
result = validate_type_id_prefix(prefix)
|
84
|
+
raise InvalidTypeIdPrefix, result if result.present?
|
85
|
+
end
|
86
|
+
|
87
|
+
def lookup_type_id(type_id)
|
88
|
+
klasses = lookup_model(type_id)
|
89
|
+
return if klasses.nil?
|
90
|
+
|
91
|
+
id = type_id # TODO: parse out the uuid part
|
92
|
+
klasses.each do |klass|
|
93
|
+
result = klass.find_by(id: id)
|
94
|
+
return result unless result.nil?
|
95
|
+
end
|
96
|
+
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def lookup_model(type_id)
|
101
|
+
prefix = get_prefix(type_id)
|
102
|
+
return if prefix.nil?
|
103
|
+
|
104
|
+
prefix_map[prefix]
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_prefix(id)
|
108
|
+
prefix, = parse_id(id)
|
109
|
+
prefix
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def parse_id(id)
|
115
|
+
id.split("_")
|
116
|
+
end
|
117
|
+
|
118
|
+
def prefix_map
|
119
|
+
Rails.application.eager_load!
|
120
|
+
# This has to be group_by and not index_by because we can have multiple
|
121
|
+
# models that use the same prefix (like Settings)
|
122
|
+
@prefix_map ||= ActiveRecord::Base.descendants
|
123
|
+
.select { |klass| klass.respond_to?(:type_id_prefix) }
|
124
|
+
.group_by(&:type_id_prefix)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RailsTypeId
|
5
|
+
# Static helpers for testing Rails models with type IDs
|
6
|
+
module TestHelper
|
7
|
+
def models_missing_type_id_prefix(base_class:, ignore_classes: [])
|
8
|
+
Rails.application.eager_load!
|
9
|
+
base_class.descendants.select do |klass|
|
10
|
+
next if ignore_classes.include?(klass)
|
11
|
+
|
12
|
+
!klass.respond_to?(:type_id_prefix)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "tapioca"
|
5
|
+
|
6
|
+
require_relative "../../../rails_type_id/concern"
|
7
|
+
|
8
|
+
module Tapioca
|
9
|
+
module Dsl
|
10
|
+
module Compilers
|
11
|
+
# This Tapioca compiler generates RBI for Rails models that include RailsTypeId::Concern.
|
12
|
+
class RailsTypeIdCompiler < Tapioca::Dsl::Compiler
|
13
|
+
extend T::Sig
|
14
|
+
|
15
|
+
ConstantType = type_member { { fixed: T.class_of(RailsTypeId::Concern) } }
|
16
|
+
|
17
|
+
RBI_MODULE_NAME = "RailsTypeIdMethods"
|
18
|
+
|
19
|
+
class << self
|
20
|
+
extend T::Sig
|
21
|
+
|
22
|
+
sig { override.returns(T::Enumerable[Module]) }
|
23
|
+
def gather_constants
|
24
|
+
all_classes
|
25
|
+
.select { |c| c < RailsTypeId::Concern }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
sig { override.void }
|
30
|
+
def decorate
|
31
|
+
root.create_path(constant) do |klass|
|
32
|
+
klass.create_module(RBI_MODULE_NAME) do |methods_mod|
|
33
|
+
methods_mod.create_method(
|
34
|
+
"type_id",
|
35
|
+
return_type: "TypeID"
|
36
|
+
)
|
37
|
+
|
38
|
+
methods_mod.create_method(
|
39
|
+
"to_param",
|
40
|
+
return_type: "String"
|
41
|
+
)
|
42
|
+
end
|
43
|
+
klass.create_include(RBI_MODULE_NAME)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/sorbet/config
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
**/*.rbi linguist-vendored=true
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# typed: true
|
2
|
+
|
3
|
+
# DO NOT EDIT MANUALLY
|
4
|
+
# This file was pulled from a central RBI files repository.
|
5
|
+
# Please run `bin/tapioca annotations` to update it.
|
6
|
+
|
7
|
+
class ActionMailer::Base
|
8
|
+
sig { params(headers: T.untyped, block: T.nilable(T.proc.params(arg0: ActionMailer::Collector).void)).returns(Mail::Message) }
|
9
|
+
def mail(headers = nil, &block); end
|
10
|
+
end
|