sorbet-rails 0.5.6 → 0.5.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +0 -2
- data/CONTRIBUTING.md +2 -4
- data/Gemfile +0 -4
- data/README.md +41 -7
- data/Rakefile +3 -14
- data/lib/bundled_rbi/parameters.rbi +4 -26
- data/lib/bundled_rbi/pluck_to_tstruct.rbi +22 -0
- data/lib/bundled_rbi/type_assert.rbi +27 -0
- data/lib/sorbet-rails/gem_plugins/elastic_search_plugin.rb +40 -0
- data/lib/sorbet-rails/gem_plugins/shrine_plugin.rb +76 -0
- data/lib/sorbet-rails/model_plugins/active_record_assoc.rb +2 -11
- data/lib/sorbet-rails/model_plugins/active_record_attribute.rb +3 -6
- data/lib/sorbet-rails/model_plugins/active_record_querying.rb +10 -2
- data/lib/sorbet-rails/model_plugins/plugins.rb +6 -0
- data/lib/sorbet-rails/rails_mixins/pluck_to_tstruct.rb +33 -0
- data/lib/sorbet-rails/railtie.rb +4 -0
- data/lib/sorbet-rails/sorbet_utils.rb +4 -1
- data/lib/sorbet-rails/tasks/rails_rbi.rake +16 -6
- data/sorbet-rails.gemspec +1 -1
- data/spec/bin/run_all_specs.sh +0 -1
- data/spec/bin/run_spec.sh +4 -6
- data/spec/generators/rails-template.rb +67 -124
- data/spec/generators/sorbet_test_cases.rb +26 -16
- data/spec/pluck_to_tstruct_spec.rb +79 -0
- data/spec/rails_helper.rb +0 -2
- data/spec/rake_rails_rbi_models_spec.rb +2 -0
- data/spec/sorbet_utils_spec.rb +37 -0
- data/spec/spec_helper.rb +1 -2
- data/spec/support/v5.0/Gemfile.lock +6 -6
- data/spec/support/v5.0/config/boot.rb +1 -1
- data/spec/support/v5.0/config/initializers/sorbet_rails.rb +1 -1
- data/spec/support/v5.0/db/migrate/20190620000004_add_more_column_types_to_wands.rb +1 -1
- data/spec/support/v5.0/sorbet_test_cases.rb +26 -16
- data/spec/support/v5.1/Gemfile.lock +6 -6
- data/spec/support/v5.1/config/boot.rb +1 -1
- data/spec/support/v5.1/config/initializers/sorbet_rails.rb +1 -1
- data/spec/support/v5.1/db/migrate/20190620000004_add_more_column_types_to_wands.rb +1 -1
- data/spec/support/v5.1/sorbet_test_cases.rb +26 -16
- data/spec/support/v5.2/Gemfile.lock +6 -6
- data/spec/support/v5.2/config/boot.rb +1 -1
- data/spec/support/v5.2/config/initializers/sorbet_rails.rb +1 -1
- data/spec/support/v5.2/db/migrate/20190620000004_add_more_column_types_to_wands.rb +1 -1
- data/spec/support/v5.2/sorbet_test_cases.rb +26 -16
- data/spec/support/v6.0/Gemfile.lock +6 -6
- data/spec/support/v6.0/config/boot.rb +1 -1
- data/spec/support/v6.0/config/initializers/sorbet_rails.rb +1 -1
- data/spec/support/v6.0/config/initializers/wrap_parameters.rb +1 -1
- data/spec/support/v6.0/db/migrate/20190620000004_add_more_column_types_to_wands.rb +1 -1
- data/spec/support/v6.0/sorbet_test_cases.rb +26 -16
- data/spec/test_data/v5.0/expected_internal_metadata.rbi +209 -197
- data/spec/test_data/v5.0/expected_potion.rbi +208 -196
- data/spec/test_data/v5.0/expected_schema_migration.rbi +209 -197
- data/spec/test_data/v5.0/expected_spell_book.rbi +208 -196
- data/spec/test_data/v5.0/expected_squib.rbi +209 -197
- data/spec/test_data/v5.0/expected_wand.rbi +208 -196
- data/spec/test_data/v5.0/expected_wizard.rbi +209 -197
- data/spec/test_data/v5.0/expected_wizard_wo_spellbook.rbi +209 -197
- data/spec/test_data/v5.1/expected_internal_metadata.rbi +213 -213
- data/spec/test_data/v5.1/expected_potion.rbi +212 -212
- data/spec/test_data/v5.1/expected_schema_migration.rbi +213 -213
- data/spec/test_data/v5.1/expected_spell_book.rbi +212 -212
- data/spec/test_data/v5.1/expected_squib.rbi +213 -213
- data/spec/test_data/v5.1/expected_wand.rbi +212 -212
- data/spec/test_data/v5.1/expected_wizard.rbi +213 -213
- data/spec/test_data/v5.1/expected_wizard_wo_spellbook.rbi +213 -213
- data/spec/test_data/v5.2/expected_attachment.rbi +212 -212
- data/spec/test_data/v5.2/expected_blob.rbi +212 -212
- data/spec/test_data/v5.2/expected_internal_metadata.rbi +213 -213
- data/spec/test_data/v5.2/expected_potion.rbi +212 -212
- data/spec/test_data/v5.2/expected_schema_migration.rbi +213 -213
- data/spec/test_data/v5.2/expected_spell_book.rbi +212 -212
- data/spec/test_data/v5.2/expected_squib.rbi +213 -213
- data/spec/test_data/v5.2/expected_wand.rbi +212 -212
- data/spec/test_data/v5.2/expected_wizard.rbi +213 -213
- data/spec/test_data/v5.2/expected_wizard_wo_spellbook.rbi +213 -213
- data/spec/test_data/v6.0/expected_attachment.rbi +244 -244
- data/spec/test_data/v6.0/expected_blob.rbi +244 -244
- data/spec/test_data/v6.0/expected_internal_metadata.rbi +245 -245
- data/spec/test_data/v6.0/expected_potion.rbi +244 -244
- data/spec/test_data/v6.0/expected_schema_migration.rbi +245 -245
- data/spec/test_data/v6.0/expected_spell_book.rbi +244 -244
- data/spec/test_data/v6.0/expected_squib.rbi +245 -245
- data/spec/test_data/v6.0/expected_wand.rbi +244 -244
- data/spec/test_data/v6.0/expected_wizard.rbi +245 -245
- data/spec/test_data/v6.0/expected_wizard_wo_spellbook.rbi +245 -245
- metadata +8 -185
- data/spec/bin/install.sh +0 -11
- data/spec/support/v4.2/.gitignore +0 -17
- data/spec/support/v4.2/Gemfile +0 -33
- data/spec/support/v4.2/Gemfile.lock +0 -128
- data/spec/support/v4.2/README.rdoc +0 -28
- data/spec/support/v4.2/Rakefile +0 -6
- data/spec/support/v4.2/app/assets/images/.keep +0 -0
- data/spec/support/v4.2/app/assets/stylesheets/application.css +0 -15
- data/spec/support/v4.2/app/controllers/application_controller.rb +0 -6
- data/spec/support/v4.2/app/controllers/concerns/.keep +0 -0
- data/spec/support/v4.2/app/helpers/application_helper.rb +0 -3
- data/spec/support/v4.2/app/helpers/bar_helper.rb +0 -3
- data/spec/support/v4.2/app/helpers/baz_helper.rb +0 -3
- data/spec/support/v4.2/app/helpers/foo_helper.rb +0 -3
- data/spec/support/v4.2/app/mailers/.keep +0 -0
- data/spec/support/v4.2/app/mailers/application_mailer.rb +0 -3
- data/spec/support/v4.2/app/mailers/daily_prophet_mailer.rb +0 -9
- data/spec/support/v4.2/app/mailers/hogwarts_acceptance_mailer.rb +0 -13
- data/spec/support/v4.2/app/models/.keep +0 -0
- data/spec/support/v4.2/app/models/application_record.rb +0 -4
- data/spec/support/v4.2/app/models/concerns/.keep +0 -0
- data/spec/support/v4.2/app/models/concerns/mythical.rb +0 -11
- data/spec/support/v4.2/app/models/potion.rb +0 -5
- data/spec/support/v4.2/app/models/spell_book.rb +0 -11
- data/spec/support/v4.2/app/models/squib.rb +0 -6
- data/spec/support/v4.2/app/models/wand.rb +0 -19
- data/spec/support/v4.2/app/models/wizard.rb +0 -29
- data/spec/support/v4.2/app/views/layouts/application.html.erb +0 -13
- data/spec/support/v4.2/bin/bundle +0 -3
- data/spec/support/v4.2/bin/rails +0 -4
- data/spec/support/v4.2/bin/rake +0 -4
- data/spec/support/v4.2/bin/setup +0 -29
- data/spec/support/v4.2/config.ru +0 -4
- data/spec/support/v4.2/config/application.rb +0 -36
- data/spec/support/v4.2/config/boot.rb +0 -4
- data/spec/support/v4.2/config/database.yml +0 -25
- data/spec/support/v4.2/config/environment.rb +0 -6
- data/spec/support/v4.2/config/environments/development.rb +0 -29
- data/spec/support/v4.2/config/environments/production.rb +0 -68
- data/spec/support/v4.2/config/environments/test.rb +0 -43
- data/spec/support/v4.2/config/initializers/backtrace_silencers.rb +0 -8
- data/spec/support/v4.2/config/initializers/cookies_serializer.rb +0 -4
- data/spec/support/v4.2/config/initializers/filter_parameter_logging.rb +0 -5
- data/spec/support/v4.2/config/initializers/inflections.rb +0 -17
- data/spec/support/v4.2/config/initializers/mime_types.rb +0 -5
- data/spec/support/v4.2/config/initializers/session_store.rb +0 -4
- data/spec/support/v4.2/config/initializers/sorbet_rails.rb +0 -3
- data/spec/support/v4.2/config/initializers/to_time_preserves_timezone.rb +0 -11
- data/spec/support/v4.2/config/initializers/wrap_parameters.rb +0 -15
- data/spec/support/v4.2/config/locales/en.yml +0 -23
- data/spec/support/v4.2/config/routes.rb +0 -58
- data/spec/support/v4.2/db/migrate/20190620000001_create_wizards.rb +0 -13
- data/spec/support/v4.2/db/migrate/20190620000002_create_wands.rb +0 -12
- data/spec/support/v4.2/db/migrate/20190620000003_create_spell_books.rb +0 -10
- data/spec/support/v4.2/db/migrate/20190620000004_add_more_column_types_to_wands.rb +0 -17
- data/spec/support/v4.2/db/migrate/20190620000005_add_broom_to_wizard.rb +0 -6
- data/spec/support/v4.2/db/migrate/20190620000007_add_type_to_wizard.rb +0 -6
- data/spec/support/v4.2/db/schema.rb +0 -49
- data/spec/support/v4.2/db/seeds.rb +0 -8
- data/spec/support/v4.2/lib/assets/.keep +0 -0
- data/spec/support/v4.2/lib/mythical_rbi_plugin.rb +0 -16
- data/spec/support/v4.2/lib/tasks/.keep +0 -0
- data/spec/support/v4.2/log/.keep +0 -0
- data/spec/support/v4.2/sorbet_test_cases.rb +0 -238
- data/spec/support/v4.2/test/controllers/.keep +0 -0
- data/spec/support/v4.2/test/fixtures/.keep +0 -0
- data/spec/support/v4.2/test/helpers/.keep +0 -0
- data/spec/support/v4.2/test/integration/.keep +0 -0
- data/spec/support/v4.2/test/mailers/.keep +0 -0
- data/spec/support/v4.2/test/models/.keep +0 -0
- data/spec/support/v4.2/test/test_helper.rb +0 -11
- data/spec/support/v4.2/typed-override.yaml +0 -2
- data/spec/support/v4.2/vendor/assets/stylesheets/.keep +0 -0
- data/spec/test_data/v4.2/expected_application_mailer.rbi +0 -5
- data/spec/test_data/v4.2/expected_daily_prophet_mailer.rbi +0 -7
- data/spec/test_data/v4.2/expected_helpers.rbi +0 -22
- data/spec/test_data/v4.2/expected_helpers_with_application_and_devise_helpers.rbi +0 -29
- data/spec/test_data/v4.2/expected_hogwarts_acceptance_mailer.rbi +0 -10
- data/spec/test_data/v4.2/expected_no_routes.rbi +0 -4
- data/spec/test_data/v4.2/expected_potion.rbi +0 -657
- data/spec/test_data/v4.2/expected_routes.rbi +0 -19
- data/spec/test_data/v4.2/expected_spell_book.rbi +0 -771
- data/spec/test_data/v4.2/expected_squib.rbi +0 -912
- data/spec/test_data/v4.2/expected_srb_tc_output.txt +0 -65
- data/spec/test_data/v4.2/expected_wand.rbi +0 -873
- data/spec/test_data/v4.2/expected_wizard.rbi +0 -912
- data/spec/test_data/v4.2/expected_wizard_wo_spellbook.rbi +0 -912
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8a83533dd2f5cd4cd6dc60f015808792494c7826240edd37c04e8de10aa4089
|
4
|
+
data.tar.gz: 9162300d63a55b865a901d55a2e76261ebf64ac003fae61d1904c8656c37b879
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21c050153045a1d5dab06bea09e8e571fbf598b073f53d9da34f42bd446dd79b43d67076f8f686e1e534306797253763bee825c0ec3d28dbcc0bc0bba86247be
|
7
|
+
data.tar.gz: a25bdfdfa28cab5ea91233ae34ae116005f9a7b99481892851a4af74d70ffee75dfba2618bb91f557b07fe97ef5335b4072f2d8fbe678e5afb644183b02d450d
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
language: ruby
|
2
2
|
env:
|
3
3
|
matrix:
|
4
|
-
- RAILS_VERSION=4.2
|
5
4
|
- RAILS_VERSION=5.0
|
6
5
|
- RAILS_VERSION=5.1
|
7
6
|
- RAILS_VERSION=5.2
|
@@ -28,7 +27,6 @@ matrix:
|
|
28
27
|
before_install:
|
29
28
|
- gem install bundler -v 2.0.1 --no-doc
|
30
29
|
- gem install bundler -v 1.17.3 --no-doc
|
31
|
-
install: "./spec/bin/install.sh"
|
32
30
|
script:
|
33
31
|
- (cd lib && bundle exec srb tc)
|
34
32
|
- "./spec/bin/run_spec.sh"
|
data/CONTRIBUTING.md
CHANGED
@@ -87,7 +87,6 @@ To run the tests against all supported Rails branches, use:
|
|
87
87
|
You can also switch to a version of Rails with `RAILS_VERSION`:
|
88
88
|
|
89
89
|
```sh
|
90
|
-
❯ RAILS_VERSION=4.2 ./spec/bin/run_spec.sh
|
91
90
|
❯ RAILS_VERSION=5.0 ./spec/bin/run_spec.sh
|
92
91
|
❯ RAILS_VERSION=5.1 ./spec/bin/run_spec.sh
|
93
92
|
❯ RAILS_VERSION=5.2 ./spec/bin/run_spec.sh
|
@@ -124,9 +123,8 @@ copied into each app with `cp`.
|
|
124
123
|
The `rails-template.rb` file uses the
|
125
124
|
[Rails Application Template](https://guides.rubyonrails.org/rails_application_templates.html)
|
126
125
|
functionality included in Rails. You can then regenerate each Rails app from
|
127
|
-
the same file using `bundle
|
128
|
-
`bundle exec rake update_spec:v5_1`, etc. (or just `bundle exec rake update_spec:
|
129
|
-
though this excludes regenerating 4.2 because 4.2 blocks usage of Bundler 2.x).
|
126
|
+
the same file using `bundle exec rake update_spec:v5_0`,
|
127
|
+
`bundle exec rake update_spec:v5_1`, etc. (or just `bundle exec rake update_spec:all`.
|
130
128
|
|
131
129
|
#### Expected Output
|
132
130
|
|
data/Gemfile
CHANGED
@@ -13,10 +13,6 @@ case rails_version
|
|
13
13
|
when "master"
|
14
14
|
gem "rails", {github: "rails/rails"}
|
15
15
|
gem "bundler", ">= 1.3.0"
|
16
|
-
when "4.2"
|
17
|
-
gem "rails", "~> 4.2.11"
|
18
|
-
gem "bundler", "~> 1.17.3"
|
19
|
-
gem "sqlite3", "~> 1.3.6"
|
20
16
|
when "5.0"
|
21
17
|
gem "rails", "~> 5.0.7"
|
22
18
|
gem "bundler", ">= 2.0"
|
data/README.md
CHANGED
@@ -27,13 +27,15 @@ gem 'sorbet-rails'
|
|
27
27
|
❯ bundle install
|
28
28
|
```
|
29
29
|
|
30
|
+
Warning: *don't* add `sorbet-rails` to a specific environment group (eg. `development` only). `sorbet-rails` adds a bunch of helper methods to your Rails runtime as well as generators for RBI files. You'll want to run the gem in all environments.
|
31
|
+
|
30
32
|
3. Generate RBI files for your routes, models, etc
|
31
33
|
```sh
|
32
34
|
❯ rake rails_rbi:routes
|
33
35
|
❯ rake rails_rbi:models
|
34
36
|
❯ rake rails_rbi:helpers
|
35
37
|
❯ rake rails_rbi:mailers
|
36
|
-
❯ rake rails_rbi:
|
38
|
+
❯ rake rails_rbi:custom
|
37
39
|
|
38
40
|
# or run them all at once
|
39
41
|
❯ rake rails_rbi:all
|
@@ -54,7 +56,7 @@ This Rake task generates RBI files for all models in the Rails application (all
|
|
54
56
|
```sh
|
55
57
|
❯ rake rails_rbi:models
|
56
58
|
```
|
57
|
-
You can also regenerate RBI files for specific models
|
59
|
+
You can also regenerate RBI files for specific models. To accommodate for STI, this will generate rbi for all the subclasses of the models included.
|
58
60
|
```sh
|
59
61
|
❯ rake rails_rbi:models[ModelName,AnotherOne,...]
|
60
62
|
```
|
@@ -68,15 +70,19 @@ The generation task currently creates the following signatures:
|
|
68
70
|
|
69
71
|
It is possible to add custom RBI generation logic for your custom module or gems via the plugin system. Check out the [plugins section](#extending-model-generation-task-with-custom-plugins) below if you are interested.
|
70
72
|
|
73
|
+
We also add following methods to make type-checking more easily:
|
74
|
+
- [`find_n`, `first_n`, `last_n`](https://github.com/chanzuckerberg/sorbet-rails#find-first-and-last)
|
75
|
+
- [`pluck_to_tstruct`](#pluck_to_tstruct-instead-of-pluck)
|
76
|
+
|
71
77
|
### Controllers
|
72
78
|
```sh
|
73
|
-
❯ rake rails_rbi:
|
79
|
+
❯ rake rails_rbi:custom
|
74
80
|
```
|
75
81
|
|
76
82
|
`sorbet-rails` adds methods to extract typed parameters from `params`, namely `require_typed` and `fetch_typed`. They are direct replacement of `require` and `fetch` that return typed object. They have the same API their counterpart, with an addition of the parameter's type, which can be any type understood by `sorbet`
|
77
83
|
|
78
84
|
This is the conversion in essence:
|
79
|
-
```
|
85
|
+
```ruby
|
80
86
|
params.require(:key) -> params.require_typed(:key, TA[Type].new)
|
81
87
|
params.fetch(:key) -> params.fetch_typed(:key, TA[Type].new)
|
82
88
|
params.fetch(:key, default_value) -> params.fetch_typed(:key, TA[Type].new, default_value)
|
@@ -84,7 +90,7 @@ params[:key] -> params.fetch_typed(:key, TA[T.nilable(Type)
|
|
84
90
|
```
|
85
91
|
|
86
92
|
For example:
|
87
|
-
```
|
93
|
+
```ruby
|
88
94
|
# require_typed
|
89
95
|
key = params.require_typed(:key, TA[String].new)
|
90
96
|
T.reveal_type(key) # String
|
@@ -230,6 +236,30 @@ with:
|
|
230
236
|
Model.unscoped.scoping do … end
|
231
237
|
```
|
232
238
|
|
239
|
+
### `select` with a block
|
240
|
+
|
241
|
+
The [`select` method](https://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/select) in Rails has two modes: it can be given a list of symbols, in which case rails will only return the given columns from the database, or it can be given a block, in which case it acts like [`Enumerable.select`](https://ruby-doc.org/core-2.6.4/Enumerable.html) and returns an array. We have chosen to support the first use case. If you want to pass a block to `select`, you can simply call `to_a` before you do. Note that this would be done within the `select` call anyway, so the performance penalty will be minimal.
|
242
|
+
|
243
|
+
### `pluck_to_tstruct` instead of `pluck`
|
244
|
+
|
245
|
+
The [`pluck` method](https://apidock.com/rails/ActiveRecord/Calculations/pluck) in Rails is a performant way to query value without instantiating ActiveRecord objects. However, it doesn't have any type information: it doesn't have type information (or name) of the attribute plucked. Sorbet-rails provides `pluck_to_tstruct` method as a replacement that does the same thing, but creates `T::Struct` object instead, and returns an array of `T::Struct`. The attributes plucked is based on props defined in the `T::Struct`
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
# -- API
|
249
|
+
Arel.pluck_to_tstruct(TA[ <TStructSubClass> ].new)
|
250
|
+
|
251
|
+
# -- example
|
252
|
+
class WizardStruct < T::Struct
|
253
|
+
const :name, String
|
254
|
+
const :house, T.nilable(String)
|
255
|
+
end
|
256
|
+
|
257
|
+
Wizard.pluck_to_tstruct(TA[WizardStruct].new) # T::Array[WizardStruct]
|
258
|
+
Wizard.all.pluck_to_tstruct(TA[WizardStruct].new) # T::Array[WizardStruct]
|
259
|
+
```
|
260
|
+
|
261
|
+
This method is based on [pluck_to_hash](https://github.com/girishso/pluck_to_hash) gem.
|
262
|
+
|
233
263
|
## Extending Model Generation Task with Custom Plugins
|
234
264
|
|
235
265
|
`sorbet-rails` support a customizable plugin system that you can use to generate additional RBI for each model. This will be useful to generate RBI for methods dynamically added by gems or private concerns. If you write plugins for public gems, please feel free to contribute it to this repo.
|
@@ -307,16 +337,20 @@ These are the currently-supported gems and their symbolized names:
|
|
307
337
|
|
308
338
|
| Gem | Symbol |
|
309
339
|
|--------------|----------------|
|
340
|
+
| [ElasticSearch]| `:elastic_search` |
|
341
|
+
| [FriendlyId] | `:friendly_id` |
|
310
342
|
| [Kaminari] | `:kaminari` |
|
311
343
|
| [PgSearch] | `:pg_search` |
|
312
|
-
| [
|
344
|
+
| [Shrine] | `:shrine` |
|
313
345
|
|
314
|
-
You can also configure the core model plugins if needed. The default plugins are defined in the [config](https://github.com/chanzuckerberg/sorbet-rails/blob/master/lib/sorbet-rails/
|
346
|
+
You can also configure the core model plugins if needed. The default plugins are defined in the [config](https://github.com/chanzuckerberg/sorbet-rails/blob/master/lib/sorbet-rails/config.rb). For the full list of plugin symbols, check out [here](https://github.com/chanzuckerberg/sorbet-rails/blob/master/lib/sorbet-rails/model_plugins/plugins.rb).
|
315
347
|
|
316
348
|
|
317
349
|
[Kaminari]: https://github.com/kaminari/kaminari
|
318
350
|
[PgSearch]: https://github.com/Casecommons/pg_search
|
319
351
|
[FriendlyId]: https://github.com/norman/friendly_id
|
352
|
+
[ElasticSearch]: https://github.com/elastic/elasticsearch-rails
|
353
|
+
[Shrine]: https://github.com/shrinerb/shrine
|
320
354
|
|
321
355
|
## Contributing
|
322
356
|
|
data/Rakefile
CHANGED
@@ -8,9 +8,8 @@ task :default => :spec
|
|
8
8
|
namespace :update_spec do
|
9
9
|
require 'fileutils'
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
task :v5_plus do |t, args|
|
11
|
+
desc "Generate Rails apps for all versions."
|
12
|
+
task :all do |t, args|
|
14
13
|
Rake::Task['update_spec:v6_0'].invoke
|
15
14
|
Rake::Task['update_spec:v5_2'].invoke
|
16
15
|
Rake::Task['update_spec:v5_1'].invoke
|
@@ -57,19 +56,9 @@ namespace :update_spec do
|
|
57
56
|
end
|
58
57
|
end
|
59
58
|
|
60
|
-
desc "Delete the Rails 4.2 spec directory and regenerate it."
|
61
|
-
task :v4_2 do |t, args|
|
62
|
-
Bundler.with_clean_env do
|
63
|
-
FileUtils.rm_rf 'spec/support/v4.2' if File.directory?('spec/support/v4.2')
|
64
|
-
system("gem install rails -v 4.2.11")
|
65
|
-
system("rails _4.2.11_ -v")
|
66
|
-
system("RAILS_VERSION='4.2' rails _4.2.11_ new --template spec/generators/rails-template.rb spec/support/v4.2 --skip-javascript --skip-test --skip-sprockets --skip-spring --skip-listen")
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
59
|
desc "Update sorbet_test_cases.rb in all the Rails apps in spec/support."
|
71
60
|
task :sorbet_test_cases do |t, args|
|
72
|
-
['v6.0', 'v5.2', 'v5.1', 'v5.0'
|
61
|
+
['v6.0', 'v5.2', 'v5.1', 'v5.0'].each do |version|
|
73
62
|
FileUtils.cp("spec/generators/sorbet_test_cases.rb", "spec/support/#{version}/sorbet_test_cases.rb")
|
74
63
|
end
|
75
64
|
end
|
@@ -1,31 +1,5 @@
|
|
1
1
|
# typed: strong
|
2
2
|
|
3
|
-
module ITypeAssert
|
4
|
-
extend T::Sig
|
5
|
-
extend T::Generic
|
6
|
-
|
7
|
-
Elem = type_member(:out)
|
8
|
-
|
9
|
-
abstract!
|
10
|
-
|
11
|
-
sig { abstract.params(val: T.untyped).returns(Elem) }
|
12
|
-
def assert(val); end
|
13
|
-
end
|
14
|
-
|
15
|
-
module TypeAssertImpl; end
|
16
|
-
|
17
|
-
class TA
|
18
|
-
extend T::Sig
|
19
|
-
extend T::Generic
|
20
|
-
include ITypeAssert
|
21
|
-
extend TypeAssertImpl
|
22
|
-
|
23
|
-
Elem = type_member
|
24
|
-
|
25
|
-
sig { override.params(val: T.untyped).returns(Elem) }
|
26
|
-
def assert(val); end
|
27
|
-
end
|
28
|
-
|
29
3
|
module SorbetRails::CustomParamsMethods
|
30
4
|
extend T::Sig
|
31
5
|
|
@@ -48,3 +22,7 @@ module SorbetRails::CustomParamsMethods
|
|
48
22
|
}
|
49
23
|
def fetch_typed(key, ta, *args); end
|
50
24
|
end
|
25
|
+
|
26
|
+
class ActionController::Parameters
|
27
|
+
include SorbetRails::CustomParamsMethods
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# typed: strong
|
2
|
+
|
3
|
+
module SorbetRails::PluckToTStruct
|
4
|
+
extend T::Sig
|
5
|
+
sig {
|
6
|
+
type_parameters(:U).
|
7
|
+
params(
|
8
|
+
ta_struct: ITypeAssert[T.type_parameter(:U)],
|
9
|
+
).
|
10
|
+
returns(T::Array[T.type_parameter(:U)])
|
11
|
+
}
|
12
|
+
def pluck_to_tstruct(ta_struct, &blk); end
|
13
|
+
end
|
14
|
+
|
15
|
+
class ActiveRecord::Base
|
16
|
+
extend SorbetRails::PluckToTStruct
|
17
|
+
end
|
18
|
+
|
19
|
+
class ActiveRecord::Relation
|
20
|
+
Elem = type_member
|
21
|
+
include SorbetRails::PluckToTStruct
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# typed: strong
|
2
|
+
|
3
|
+
module ITypeAssert
|
4
|
+
extend T::Sig
|
5
|
+
extend T::Generic
|
6
|
+
|
7
|
+
Elem = type_member(:out)
|
8
|
+
|
9
|
+
abstract!
|
10
|
+
|
11
|
+
sig { abstract.params(val: T.untyped).returns(Elem) }
|
12
|
+
def assert(val); end
|
13
|
+
end
|
14
|
+
|
15
|
+
module TypeAssertImpl; end
|
16
|
+
|
17
|
+
class TA
|
18
|
+
extend T::Sig
|
19
|
+
extend T::Generic
|
20
|
+
include ITypeAssert
|
21
|
+
extend TypeAssertImpl
|
22
|
+
|
23
|
+
Elem = type_member
|
24
|
+
|
25
|
+
sig { override.params(val: T.untyped).returns(Elem) }
|
26
|
+
def assert(val); end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# typed: true
|
2
|
+
class ElasticSearchPlugin < SorbetRails::ModelPlugins::Base
|
3
|
+
sig { override.params(root: Parlour::RbiGenerator::Namespace).void }
|
4
|
+
def generate(root)
|
5
|
+
return unless @model_class.include?(::Elasticsearch::Model)
|
6
|
+
|
7
|
+
model_rbi = root.create_class(model_class_name)
|
8
|
+
model_rbi.create_method(
|
9
|
+
'mapping',
|
10
|
+
class_method: true,
|
11
|
+
parameters: [
|
12
|
+
::Parlour::RbiGenerator::Parameter.new(
|
13
|
+
"options",
|
14
|
+
type: "T.nilable(T::Hash[Symbol, T.untyped])", default: 'nil',
|
15
|
+
),
|
16
|
+
::Parlour::RbiGenerator::Parameter.new(
|
17
|
+
"&block",
|
18
|
+
type: "T.proc.bind(Elasticsearch::Model::Indexing::Mappings).void",
|
19
|
+
)
|
20
|
+
],
|
21
|
+
return_type: "Elasticsearch::Model::Indexing::Mappings",
|
22
|
+
)
|
23
|
+
|
24
|
+
model_rbi.create_method(
|
25
|
+
'mappings',
|
26
|
+
class_method: true,
|
27
|
+
parameters: [
|
28
|
+
::Parlour::RbiGenerator::Parameter.new(
|
29
|
+
"options",
|
30
|
+
type: "T.nilable(T::Hash[Symbol, T.untyped])", default: 'nil',
|
31
|
+
),
|
32
|
+
::Parlour::RbiGenerator::Parameter.new(
|
33
|
+
"&block",
|
34
|
+
type: "T.proc.bind(Elasticsearch::Model::Indexing::Mappings).void",
|
35
|
+
)
|
36
|
+
],
|
37
|
+
return_type: "Elasticsearch::Model::Indexing::Mappings",
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# typed: false
|
2
|
+
class ShrinePlugin < SorbetRails::ModelPlugins::Base
|
3
|
+
sig { override.params(root: Parlour::RbiGenerator::Namespace).void }
|
4
|
+
def generate(root)
|
5
|
+
model_rbi = root.create_class(model_class_name)
|
6
|
+
processed_attachments = Set.new
|
7
|
+
@model_class.included_modules.each do |included_module|
|
8
|
+
# based on https://github.com/shrinerb/shrine/blob/master/lib/shrine/attachment.rb
|
9
|
+
if included_module.is_a?(Shrine::Attachment)
|
10
|
+
attachment_name = included_module.attachment_name.to_s
|
11
|
+
next if processed_attachments.include?(attachment_name)
|
12
|
+
processed_attachments.add(attachment_name)
|
13
|
+
|
14
|
+
# TODO: detect nilability based on column nilability
|
15
|
+
model_rbi.create_method(
|
16
|
+
attachment_name,
|
17
|
+
return_type: "T.nilable(#{included_module.shrine_class}::UploadedFile)",
|
18
|
+
)
|
19
|
+
model_rbi.create_method(
|
20
|
+
"#{attachment_name}=",
|
21
|
+
parameters: [
|
22
|
+
::Parlour::RbiGenerator::Parameter.new(
|
23
|
+
"file",
|
24
|
+
type:
|
25
|
+
"T.any(String, T::Hash[T.untyped, T.untyped],
|
26
|
+
#{included_module.shrine_class}::UploadedFile)".squish!,
|
27
|
+
),
|
28
|
+
],
|
29
|
+
)
|
30
|
+
model_rbi.create_method(
|
31
|
+
"#{attachment_name}_attacher",
|
32
|
+
return_type: "T.nilable(#{included_module.shrine_class}::Attacher)",
|
33
|
+
)
|
34
|
+
|
35
|
+
# remote_url plugin
|
36
|
+
# https://github.com/shrinerb/shrine/blob/2b7fad37dbaa955a7d3b82e9e05eaacb3506b4ba/
|
37
|
+
# ../lib/shrine/plugins/remote_url.rb
|
38
|
+
if included_module.is_a?(Shrine::Plugins::RemoteUrl::AttachmentMethods)
|
39
|
+
model_rbi.create_method(
|
40
|
+
"#{attachment_name}_remote_url",
|
41
|
+
return_type: "T.nilable(String)",
|
42
|
+
)
|
43
|
+
model_rbi.create_method(
|
44
|
+
"#{attachment_name}_remote_url=",
|
45
|
+
parameters: [
|
46
|
+
::Parlour::RbiGenerator::Parameter.new(
|
47
|
+
"url",
|
48
|
+
type: T.untyped # TODO likely T.nilable(String)
|
49
|
+
),
|
50
|
+
],
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
#--
|
55
|
+
attachment = Object.const_get("#{included_module.shrine_class}::Attachment")
|
56
|
+
attachment_rbi = root.create_class(
|
57
|
+
attachment.name,
|
58
|
+
superclass: 'Shrine::Attachment',
|
59
|
+
)
|
60
|
+
attachment_rbi.create_method(
|
61
|
+
"initialize",
|
62
|
+
parameters: [
|
63
|
+
::Parlour::RbiGenerator::Parameter.new('name', type: 'T.any(String, Symbol)'),
|
64
|
+
::Parlour::RbiGenerator::Parameter.new('**option', type: 'T.untyped'),
|
65
|
+
]
|
66
|
+
)
|
67
|
+
#--
|
68
|
+
uploaded_file = Object.const_get("#{included_module.shrine_class}::UploadedFile")
|
69
|
+
uploaded_file_rbi = root.create_class(
|
70
|
+
uploaded_file.name,
|
71
|
+
superclass: 'Shrine::UploadedFile',
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -38,17 +38,8 @@ class SorbetRails::ModelPlugins::ActiveRecordAssoc < SorbetRails::ModelPlugins::
|
|
38
38
|
assoc_type = "T.nilable(#{assoc_class})"
|
39
39
|
if reflection.belongs_to?
|
40
40
|
column_def = @columns_hash[reflection.foreign_key.to_s]
|
41
|
-
|
42
|
-
|
43
|
-
# if this is a belongs_to connection, we may be able to detect whether
|
44
|
-
# this field is required & use a stronger type
|
45
|
-
if column_def
|
46
|
-
assoc_type = assoc_class if !column_def.null
|
47
|
-
end
|
48
|
-
else
|
49
|
-
# In Rails 5 and later, belongs_to are required unless specified to be optional
|
50
|
-
assoc_type = assoc_class if !reflection.options[:optional]
|
51
|
-
end
|
41
|
+
# In Rails 5 and later, belongs_to are required unless specified to be optional
|
42
|
+
assoc_type = assoc_class if !reflection.options[:optional]
|
52
43
|
end
|
53
44
|
|
54
45
|
assoc_module_rbi.create_method(
|
@@ -75,8 +75,7 @@ class SorbetRails::ModelPlugins::ActiveRecordAttribute < SorbetRails::ModelPlugi
|
|
75
75
|
|
76
76
|
sig do
|
77
77
|
params(
|
78
|
-
|
79
|
-
klass: T.any(Object, ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter),
|
78
|
+
klass: Object,
|
80
79
|
time_zone_aware: T::Boolean,
|
81
80
|
).returns(T.any(String, Class))
|
82
81
|
end
|
@@ -88,10 +87,6 @@ class SorbetRails::ModelPlugins::ActiveRecordAttribute < SorbetRails::ModelPlugi
|
|
88
87
|
time_zone_aware ? ActiveSupport::TimeWithZone : Time
|
89
88
|
when ActiveRecord::Type::Date
|
90
89
|
Date
|
91
|
-
when ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter
|
92
|
-
# if type has already been decorated with TimeZoneConverter, it's probably
|
93
|
-
# a Rails 4.2 datetime column and can be considered a TimeWithZone
|
94
|
-
ActiveSupport::TimeWithZone
|
95
90
|
when ActiveRecord::Type::Decimal
|
96
91
|
BigDecimal
|
97
92
|
when ActiveRecord::Type::Float
|
@@ -145,6 +140,8 @@ class SorbetRails::ModelPlugins::ActiveRecordAttribute < SorbetRails::ModelPlugi
|
|
145
140
|
"T.any(#{assignable_time_types.join(', ')})"
|
146
141
|
elsif column_type == "T.nilable(ActiveSupport::TimeWithZone)"
|
147
142
|
"T.nilable(T.any(#{assignable_time_types.join(', ')}))"
|
143
|
+
elsif column_type == String
|
144
|
+
'T.any(String, Symbol)'
|
148
145
|
else
|
149
146
|
column_type.to_s
|
150
147
|
end
|