rbs_rails 0.7.0 → 0.9.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.dependabot/config.yml +5 -0
  3. data/.github/workflows/ci.yml +11 -2
  4. data/.gitignore +1 -1
  5. data/CHANGELOG.md +30 -0
  6. data/Gemfile +6 -3
  7. data/Gemfile.lock +179 -0
  8. data/README.md +11 -4
  9. data/Rakefile +4 -2
  10. data/Steepfile +1 -14
  11. data/bin/add-type-params.rb +1 -0
  12. data/bin/setup +1 -0
  13. data/lib/rbs_rails/active_record.rb +135 -18
  14. data/lib/rbs_rails/rake_task.rb +3 -14
  15. data/lib/rbs_rails/version.rb +1 -1
  16. data/rbs_collection.lock.yaml +132 -0
  17. data/rbs_collection.yaml +45 -0
  18. data/rbs_rails.gemspec +2 -2
  19. data/sig/activerecord.rbs +4 -0
  20. data/sig/rbs_rails/active_record.rbs +11 -0
  21. metadata +9 -29
  22. data/assets/sig/action_mailer.rbs +0 -8
  23. data/assets/sig/builtin.rbs +0 -7
  24. data/assets/sig/capybara.rbs +0 -14
  25. data/assets/sig/concurrent.rbs +0 -4
  26. data/assets/sig/erb.rbs +0 -4
  27. data/assets/sig/erubi.rbs +0 -4
  28. data/assets/sig/i18n.rbs +0 -4
  29. data/assets/sig/libxml.rbs +0 -10
  30. data/assets/sig/minitest.rbs +0 -13
  31. data/assets/sig/nokogiri.rbs +0 -8
  32. data/assets/sig/pg.rbs +0 -5
  33. data/assets/sig/que.rbs +0 -4
  34. data/assets/sig/queue_classic.rbs +0 -4
  35. data/assets/sig/racc.rbs +0 -4
  36. data/assets/sig/rack-test.rbs +0 -6
  37. data/assets/sig/rack.rbs +0 -47
  38. data/assets/sig/rails.rbs +0 -10
  39. data/assets/sig/rdoc.rbs +0 -9
  40. data/assets/sig/sidekiq.rbs +0 -4
  41. data/assets/sig/sneakers.rbs +0 -4
  42. data/assets/sig/stdlib.rbs +0 -24
  43. data/assets/sig/sucker_punch.rbs +0 -4
  44. data/assets/sig/thor.rbs +0 -12
  45. data/assets/sig/tzinfo.rbs +0 -4
  46. data/bin/gem_rbs +0 -94
  47. data/bin/rbs +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82919f7e04d613a702ad6cadbff8df905f23b54bf7dbdae04122a5af5df09608
4
- data.tar.gz: 7070d476fe7f15776eed7fa406c423f18ba54077b4293ccb6064c151c7a89754
3
+ metadata.gz: ccb7076ac91a406f491cf3e6c4d8499525f860660061ff23809635d000d1aba3
4
+ data.tar.gz: a863d9e16999e7491cef930b8fb79515c538ad7d83b919abad762a5c1290e370
5
5
  SHA512:
6
- metadata.gz: 92c046d0f404ff63fe86b3fab5bd92dd24731919827c5ee04330cecf26ae158608e4b0babc1097977ef5cddcbd9474983621d188b996cf264cb96a65142adf95
7
- data.tar.gz: 947c7022e0e49010cdc0fbce0bd453993f3ba0bc3df1fb5d406bce94361c49f8d61044b95ba9fed901e6635a9476b4c699812f2334e5e36552552138baada338
6
+ metadata.gz: 10dccf3356c898258d6c13aaed04d61a5f137787f9ea696fe0d7005e2063c2fd130d9fdda59c4c7b4fa58d1cde84a3ca0cf750dac28f1ac9ffbfe94ead90da57
7
+ data.tar.gz: b8f5c227bf58bdb16044867cd4abd883f21782817eda8fa6d85d1956418c763829748d5d0ee0e81e1005ffd18e022d6da6e83b64aa97cf4f77fe6942bacec48b
@@ -0,0 +1,5 @@
1
+ version: 1
2
+ update_configs:
3
+ - package_manager: "ruby:bundler"
4
+ directory: "/"
5
+ update_schedule: "live"
@@ -1,13 +1,21 @@
1
1
  name: CI
2
2
 
3
- on: [push, pull_request]
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ types:
9
+ - opened
10
+ - synchronize
11
+ - reopened
4
12
 
5
13
  jobs:
6
14
  test:
7
15
  strategy:
8
16
  fail-fast: false
9
17
  matrix:
10
- ruby: [2.6, 2.7, '3.0']
18
+ ruby: [2.6, 2.7, '3.0', head]
11
19
  runs-on: ubuntu-latest
12
20
  steps:
13
21
  - uses: actions/checkout@v2
@@ -15,4 +23,5 @@ jobs:
15
23
  with:
16
24
  ruby-version: ${{ matrix.ruby }}
17
25
  bundler-cache: true # runs 'bundle install' and caches installed gems automatically
26
+ - run: bin/setup
18
27
  - run: bundle exec rake
data/.gitignore CHANGED
@@ -6,7 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
- /Gemfile.lock
10
9
  /test/app/sig/rbs_rails
11
10
  /test/app/sig/app
12
11
  /test/app/sig/path_helpers.rbs
12
+ /.gem_rbs_collection/
data/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
2
2
 
3
3
  ## master (unreleased)
4
4
 
5
+ ## 0.9.0 (2021-09-18)
6
+
7
+ ### New Features
8
+
9
+ * Support delegated_type association. [#181](https://github.com/pocke/rbs_rails/pull/181)
10
+
11
+ ### Bug Fixes
12
+
13
+ * Fix error on a table that doesn't have the PK. [#121](https://github.com/pocke/rbs_rails/pull/121)
14
+ * Quote variable names to avoid syntax errors. [#178](https://github.com/pocke/rbs_rails/pull/178)
15
+ * Add scope methods to `ActiveRecord_Associations_CollectionProxy`. [#182](https://github.com/pocke/rbs_rails/pull/182)
16
+ * Make `has_one` association optional. [#180](https://github.com/pocke/rbs_rails/pull/180)
17
+ * Omit some methods for polymorphic associations. [#184](https://github.com/pocke/rbs_rails/pull/184)
18
+ * Include enum methods to GeneratedRelationMethods. [#183](https://github.com/pocke/rbs_rails/pull/183)
19
+ * Include `_ActiveRecord_Relation` to `CollectionProxy`. [#189](https://github.com/pocke/rbs_rails/pull/189)
20
+
21
+ ## 0.8.2 (2021-02-20)
22
+
23
+ * Add ActiveRecord::AttributeMethods::Dirty methods [#104](https://github.com/pocke/rbs_rails/pull/104)
24
+ * Define find method based on primary key [#105](https://github.com/pocke/rbs_rails/pull/105)
25
+
26
+ ## 0.8.1 (2021-01-09)
27
+
28
+ * Skip generation RBS fro class that doesn't have table in DB. [#95](https://github.com/pocke/rbs_rails/pull/95)
29
+
30
+ ## 0.8.0 (2020-12-31)
31
+
32
+ * **[BREAKING]** Move RBS files that are copied by `rbs_rails:copy_signature_files` task to [ruby/gem_rbs](https://github.com/ruby/gem_rbs) repository [#90](https://github.com/pocke/rbs_rails/pull/90)
33
+ * Allow all kinds of argument for scope [#89](https://github.com/pocke/rbs_rails/pull/89)
34
+
5
35
  ## 0.7.0 (2020-12-28)
6
36
 
7
37
  * **[BREAKING]** Re-structure signature directory. [#86](https://github.com/pocke/rbs_rails/pull/86)
data/Gemfile CHANGED
@@ -1,9 +1,12 @@
1
1
  source "https://rubygems.org"
2
2
 
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
3
5
  # Specify your gem's dependencies in rbs_rails.gemspec
4
6
  gemspec
5
7
 
6
- gem "rake", "~> 12.0"
7
- gem 'rbs', '1.0.0'
8
- gem 'steep', '>= 0.34.0', git: 'https://github.com/soutaro/steep.git'
8
+ gem "rake", "~> 13.0"
9
+ gem 'rails', '< 6.1', '>= 6.0'
10
+ gem 'rbs', '>= 1.6'
11
+ gem 'steep', github: 'soutaro/steep'
9
12
  gem 'minitest'
data/Gemfile.lock ADDED
@@ -0,0 +1,179 @@
1
+ GIT
2
+ remote: https://github.com/soutaro/steep
3
+ revision: 0673d88395fb0ea380463fef1aed568dfb077a60
4
+ specs:
5
+ steep (0.46.0)
6
+ activesupport (>= 5.1)
7
+ language_server-protocol (>= 3.15, < 4.0)
8
+ listen (~> 3.0)
9
+ parallel (>= 1.0.0)
10
+ parser (>= 3.0)
11
+ rainbow (>= 2.2.2, < 4.0)
12
+ rbs (>= 1.6.0)
13
+ terminal-table (>= 2, < 4)
14
+
15
+ PATH
16
+ remote: .
17
+ specs:
18
+ rbs_rails (0.9.0)
19
+ parser
20
+ rbs (>= 1)
21
+
22
+ GEM
23
+ remote: https://rubygems.org/
24
+ specs:
25
+ actioncable (6.0.4.1)
26
+ actionpack (= 6.0.4.1)
27
+ nio4r (~> 2.0)
28
+ websocket-driver (>= 0.6.1)
29
+ actionmailbox (6.0.4.1)
30
+ actionpack (= 6.0.4.1)
31
+ activejob (= 6.0.4.1)
32
+ activerecord (= 6.0.4.1)
33
+ activestorage (= 6.0.4.1)
34
+ activesupport (= 6.0.4.1)
35
+ mail (>= 2.7.1)
36
+ actionmailer (6.0.4.1)
37
+ actionpack (= 6.0.4.1)
38
+ actionview (= 6.0.4.1)
39
+ activejob (= 6.0.4.1)
40
+ mail (~> 2.5, >= 2.5.4)
41
+ rails-dom-testing (~> 2.0)
42
+ actionpack (6.0.4.1)
43
+ actionview (= 6.0.4.1)
44
+ activesupport (= 6.0.4.1)
45
+ rack (~> 2.0, >= 2.0.8)
46
+ rack-test (>= 0.6.3)
47
+ rails-dom-testing (~> 2.0)
48
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
49
+ actiontext (6.0.4.1)
50
+ actionpack (= 6.0.4.1)
51
+ activerecord (= 6.0.4.1)
52
+ activestorage (= 6.0.4.1)
53
+ activesupport (= 6.0.4.1)
54
+ nokogiri (>= 1.8.5)
55
+ actionview (6.0.4.1)
56
+ activesupport (= 6.0.4.1)
57
+ builder (~> 3.1)
58
+ erubi (~> 1.4)
59
+ rails-dom-testing (~> 2.0)
60
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
61
+ activejob (6.0.4.1)
62
+ activesupport (= 6.0.4.1)
63
+ globalid (>= 0.3.6)
64
+ activemodel (6.0.4.1)
65
+ activesupport (= 6.0.4.1)
66
+ activerecord (6.0.4.1)
67
+ activemodel (= 6.0.4.1)
68
+ activesupport (= 6.0.4.1)
69
+ activestorage (6.0.4.1)
70
+ actionpack (= 6.0.4.1)
71
+ activejob (= 6.0.4.1)
72
+ activerecord (= 6.0.4.1)
73
+ marcel (~> 1.0.0)
74
+ activesupport (6.0.4.1)
75
+ concurrent-ruby (~> 1.0, >= 1.0.2)
76
+ i18n (>= 0.7, < 2)
77
+ minitest (~> 5.1)
78
+ tzinfo (~> 1.1)
79
+ zeitwerk (~> 2.2, >= 2.2.2)
80
+ ast (2.4.2)
81
+ builder (3.2.4)
82
+ concurrent-ruby (1.1.9)
83
+ crass (1.0.6)
84
+ erubi (1.10.0)
85
+ ffi (1.15.4)
86
+ globalid (0.5.2)
87
+ activesupport (>= 5.0)
88
+ i18n (1.8.10)
89
+ concurrent-ruby (~> 1.0)
90
+ language_server-protocol (3.16.0.3)
91
+ listen (3.7.0)
92
+ rb-fsevent (~> 0.10, >= 0.10.3)
93
+ rb-inotify (~> 0.9, >= 0.9.10)
94
+ loofah (2.12.0)
95
+ crass (~> 1.0.2)
96
+ nokogiri (>= 1.5.9)
97
+ mail (2.7.1)
98
+ mini_mime (>= 0.1.1)
99
+ marcel (1.0.1)
100
+ method_source (1.0.0)
101
+ mini_mime (1.1.1)
102
+ mini_portile2 (2.6.1)
103
+ minitest (5.14.4)
104
+ nio4r (2.5.8)
105
+ nokogiri (1.12.4)
106
+ mini_portile2 (~> 2.6.1)
107
+ racc (~> 1.4)
108
+ parallel (1.20.1)
109
+ parser (3.0.2.0)
110
+ ast (~> 2.4.1)
111
+ racc (1.5.2)
112
+ rack (2.2.3)
113
+ rack-test (1.1.0)
114
+ rack (>= 1.0, < 3)
115
+ rails (6.0.4.1)
116
+ actioncable (= 6.0.4.1)
117
+ actionmailbox (= 6.0.4.1)
118
+ actionmailer (= 6.0.4.1)
119
+ actionpack (= 6.0.4.1)
120
+ actiontext (= 6.0.4.1)
121
+ actionview (= 6.0.4.1)
122
+ activejob (= 6.0.4.1)
123
+ activemodel (= 6.0.4.1)
124
+ activerecord (= 6.0.4.1)
125
+ activestorage (= 6.0.4.1)
126
+ activesupport (= 6.0.4.1)
127
+ bundler (>= 1.3.0)
128
+ railties (= 6.0.4.1)
129
+ sprockets-rails (>= 2.0.0)
130
+ rails-dom-testing (2.0.3)
131
+ activesupport (>= 4.2.0)
132
+ nokogiri (>= 1.6)
133
+ rails-html-sanitizer (1.4.2)
134
+ loofah (~> 2.3)
135
+ railties (6.0.4.1)
136
+ actionpack (= 6.0.4.1)
137
+ activesupport (= 6.0.4.1)
138
+ method_source
139
+ rake (>= 0.8.7)
140
+ thor (>= 0.20.3, < 2.0)
141
+ rainbow (3.0.0)
142
+ rake (13.0.6)
143
+ rb-fsevent (0.11.0)
144
+ rb-inotify (0.10.1)
145
+ ffi (~> 1.0)
146
+ rbs (1.6.2)
147
+ sprockets (4.0.2)
148
+ concurrent-ruby (~> 1.0)
149
+ rack (> 1, < 3)
150
+ sprockets-rails (3.2.2)
151
+ actionpack (>= 4.0)
152
+ activesupport (>= 4.0)
153
+ sprockets (>= 3.0.0)
154
+ terminal-table (3.0.1)
155
+ unicode-display_width (>= 1.1.1, < 3)
156
+ thor (1.1.0)
157
+ thread_safe (0.3.6)
158
+ tzinfo (1.2.9)
159
+ thread_safe (~> 0.1)
160
+ unicode-display_width (2.0.0)
161
+ websocket-driver (0.7.5)
162
+ websocket-extensions (>= 0.1.0)
163
+ websocket-extensions (0.1.5)
164
+ zeitwerk (2.4.2)
165
+
166
+ PLATFORMS
167
+ ruby
168
+ x86_64-linux
169
+
170
+ DEPENDENCIES
171
+ minitest
172
+ rails (>= 6.0, < 6.1)
173
+ rake (~> 13.0)
174
+ rbs (>= 1.6)
175
+ rbs_rails!
176
+ steep!
177
+
178
+ BUNDLED WITH
179
+ 2.2.27
data/README.md CHANGED
@@ -28,9 +28,8 @@ require 'rbs_rails/rake_task'
28
28
  RbsRails::RakeTask.new
29
29
  ```
30
30
 
31
- Then, the following four tasks are available.
31
+ Then, the following three tasks are available.
32
32
 
33
- * `rbs_rails:copy_signature_files`: Copy RBS files for rbs_rails
34
33
  * `rbs_rails:generate_rbs_for_models`: Generate RBS files for Active Record models
35
34
  * `rbs_rails:generate_rbs_for_path_helpers`: Generate RBS files for path helpers
36
35
  * `rbs_rails:all`: Execute all tasks of RBS Rails
@@ -56,6 +55,12 @@ target :app do
56
55
  library 'logger'
57
56
  library 'mutex_m'
58
57
  library 'date'
58
+ library 'monitor'
59
+ library 'singleton'
60
+ library 'tsort'
61
+ library 'time'
62
+
63
+ library 'rack'
59
64
 
60
65
  library 'activesupport'
61
66
  library 'actionpack'
@@ -67,11 +72,13 @@ target :app do
67
72
  end
68
73
  ```
69
74
 
70
- You need to put RBS repo to `path/to/rbs_repo`. See https://github.com/ruby/gem_rbs
75
+ You need to put RBS repo to `path/to/rbs_repo`. See https://github.com/ruby/gem_rbs_collection
71
76
 
72
77
  ## Development
73
78
 
74
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
79
+ After checking out the repo, run `bin/setup` to install dependencies.
80
+
81
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
75
82
 
76
83
  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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
77
84
 
data/Rakefile CHANGED
@@ -9,8 +9,10 @@ task :steep do
9
9
  end
10
10
 
11
11
  task :rbs_validate do
12
- rbs = Pathname(__dir__).join('bin/rbs').to_s
13
- sh "ruby #{rbs} validate --silent"
12
+ repo = ENV['RBS_REPO_DIR']&.then do |env|
13
+ "--repo=#{env}"
14
+ end
15
+ sh "rbs #{repo} validate --silent"
14
16
  end
15
17
 
16
18
  Rake::TestTask.new do |test|
data/Steepfile CHANGED
@@ -3,18 +3,5 @@ target :lib do
3
3
  signature 'assets/sig'
4
4
 
5
5
  check "lib" # Directory name
6
- repo_path ENV['RBS_REPO_DIR'] || './gem_rbs/gems'
7
-
8
- library "pathname"
9
- library "logger"
10
- library "mutex_m"
11
- library "date"
12
-
13
- library 'activesupport'
14
- library 'actionpack'
15
- library 'activejob'
16
- library 'activemodel'
17
- library 'actionview'
18
- library 'activerecord'
19
- library 'railties'
6
+ repo_path ENV['RBS_REPO_DIR'] if ENV['RBS_REPO_DIR']
20
7
  end
@@ -16,6 +16,7 @@ end
16
16
  def env
17
17
  @env ||= begin
18
18
  loader = RBS::EnvironmentLoader.new()
19
+ loader.add(library: 'tsort')
19
20
  RBS::Environment.from_loader(loader).resolve_type_names
20
21
  end
21
22
  end
data/bin/setup CHANGED
@@ -4,5 +4,6 @@ IFS=$'\n\t'
4
4
  set -vx
5
5
 
6
6
  bundle install
7
+ bundle exec rbs collection install --frozen
7
8
 
8
9
  # Do any other automated setup that you need to do here
@@ -1,6 +1,12 @@
1
1
  module RbsRails
2
2
  module ActiveRecord
3
3
 
4
+ def self.generatable?(klass)
5
+ return false if klass.abstract_class?
6
+
7
+ klass.connection.table_exists?(klass.table_name)
8
+ end
9
+
4
10
  def self.class_to_rbs(klass, dependencies: [])
5
11
  Generator.new(klass, dependencies: dependencies).generate
6
12
  end
@@ -22,14 +28,18 @@ module RbsRails
22
28
  private def klass_decl
23
29
  <<~RBS
24
30
  #{header}
25
- extend _ActiveRecord_Relation_ClassMethods[#{klass_name}, #{relation_class_name}]
31
+ extend _ActiveRecord_Relation_ClassMethods[#{klass_name}, #{relation_class_name}, #{pk_type}]
26
32
 
27
33
  #{columns}
28
34
  #{associations}
35
+ #{delegated_type_instance}
36
+ #{delegated_type_scope(singleton: true)}
29
37
  #{enum_instance_methods}
30
38
  #{enum_scope_methods(singleton: true)}
31
39
  #{scopes(singleton: true)}
32
40
 
41
+ #{generated_relation_methods_decl}
42
+
33
43
  #{relation_decl}
34
44
 
35
45
  #{collection_proxy_decl}
@@ -38,13 +48,30 @@ module RbsRails
38
48
  RBS
39
49
  end
40
50
 
51
+ private def pk_type
52
+ pk = klass.primary_key
53
+ return 'top' unless pk
54
+
55
+ col = klass.columns.find {|col| col.name == pk }
56
+ sql_type_to_class(col.type)
57
+ end
58
+
59
+ private def generated_relation_methods_decl
60
+ <<~RBS
61
+ module GeneratedRelationMethods
62
+ #{enum_scope_methods(singleton: false)}
63
+ #{scopes(singleton: false)}
64
+ #{delegated_type_scope(singleton: false)}
65
+ end
66
+ RBS
67
+ end
68
+
41
69
  private def relation_decl
42
70
  <<~RBS
43
71
  class #{relation_class_name} < ActiveRecord::Relation
44
- include _ActiveRecord_Relation[#{klass_name}]
72
+ include GeneratedRelationMethods
73
+ include _ActiveRecord_Relation[#{klass_name}, #{pk_type}]
45
74
  include Enumerable[#{klass_name}]
46
- #{enum_scope_methods(singleton: false)}
47
- #{scopes(singleton: false)}
48
75
  end
49
76
  RBS
50
77
  end
@@ -52,6 +79,8 @@ module RbsRails
52
79
  private def collection_proxy_decl
53
80
  <<~RBS
54
81
  class ActiveRecord_Associations_CollectionProxy < ActiveRecord::Associations::CollectionProxy
82
+ include GeneratedRelationMethods
83
+ include _ActiveRecord_Relation[#{klass_name}, #{pk_type}]
55
84
  end
56
85
  RBS
57
86
  end
@@ -108,7 +137,7 @@ module RbsRails
108
137
  type = a.polymorphic? ? 'untyped' : Util.module_name(a.klass)
109
138
  type_optional = optional(type)
110
139
  <<~RUBY.chomp
111
- def #{a.name}: () -> #{type}
140
+ def #{a.name}: () -> #{type_optional}
112
141
  def #{a.name}=: (#{type_optional}) -> #{type_optional}
113
142
  def build_#{a.name}: (untyped) -> #{type}
114
143
  def create_#{a.name}: (untyped) -> #{type}
@@ -122,17 +151,91 @@ module RbsRails
122
151
  klass.reflect_on_all_associations(:belongs_to).map do |a|
123
152
  type = a.polymorphic? ? 'untyped' : Util.module_name(a.klass)
124
153
  type_optional = optional(type)
125
- <<~RUBY.chomp
126
- def #{a.name}: () -> #{type}
127
- def #{a.name}=: (#{type_optional}) -> #{type_optional}
128
- def build_#{a.name}: (untyped) -> #{type}
129
- def create_#{a.name}: (untyped) -> #{type}
130
- def create_#{a.name}!: (untyped) -> #{type}
131
- def reload_#{a.name}: () -> #{type_optional}
132
- RUBY
154
+ # @type var methods: Array[String]
155
+ methods = []
156
+ methods << "def #{a.name}: () -> #{type}"
157
+ methods << "def #{a.name}=: (#{type_optional}) -> #{type_optional}"
158
+ methods << "def reload_#{a.name}: () -> #{type_optional}"
159
+ if !a.polymorphic?
160
+ methods << "def build_#{a.name}: (untyped) -> #{type}"
161
+ methods << "def create_#{a.name}: (untyped) -> #{type}"
162
+ methods << "def create_#{a.name}!: (untyped) -> #{type}"
163
+ end
164
+ methods.join("\n")
133
165
  end.join("\n")
134
166
  end
135
167
 
168
+ private def delegated_type_scope(singleton:)
169
+ definitions = delegated_type_definitions
170
+ return "" unless definitions
171
+ definitions.map do |definition|
172
+ definition[:types].map do |type|
173
+ scope_name = type.tableize.gsub("/", "_")
174
+ "def #{singleton ? 'self.' : ''}#{scope_name}: () -> #{relation_class_name}"
175
+ end
176
+ end.flatten.join("\n")
177
+ end
178
+
179
+ private def delegated_type_instance
180
+ definitions = delegated_type_definitions
181
+ return "" unless definitions
182
+ # @type var methods: Array[String]
183
+ methods = []
184
+ definitions.each do |definition|
185
+ methods << "def #{definition[:role]}_class: () -> Class"
186
+ methods << "def #{definition[:role]}_name: () -> String"
187
+ methods << definition[:types].map do |type|
188
+ scope_name = type.tableize.gsub("/", "_")
189
+ singular = scope_name.singularize
190
+ <<~RUBY.chomp
191
+ def #{singular}?: () -> bool
192
+ def #{singular}: () -> #{type.classify}?
193
+ def #{singular}_id: () -> Integer?
194
+ RUBY
195
+ end.join("\n")
196
+ end
197
+ methods.join("\n")
198
+ end
199
+
200
+ private def delegated_type_definitions
201
+ ast = parse_model_file
202
+ return unless ast
203
+
204
+ traverse(ast).map do |node|
205
+ # @type block: { role: Symbol, types: Array[String] }?
206
+ next unless node.type == :send
207
+ next unless node.children[0].nil?
208
+ next unless node.children[1] == :delegated_type
209
+
210
+ role_node = node.children[2]
211
+ next unless role_node
212
+ next unless role_node.type == :sym
213
+ # @type var role: Symbol
214
+ role = role_node.children[0]
215
+
216
+ args_node = node.children[3]
217
+ next unless args_node
218
+ next unless args_node.type == :hash
219
+
220
+ types = traverse(args_node).map do |n|
221
+ # @type block: Array[String]?
222
+ next unless n.type == :pair
223
+ key_node = n.children[0]
224
+ next unless key_node
225
+ next unless key_node.type == :sym
226
+ next unless key_node.children[0] == :types
227
+
228
+ types_node = n.children[1]
229
+ next unless types_node
230
+ next unless types_node.type == :array
231
+ code = types_node.loc.expression.source
232
+ eval(code)
233
+ end.compact.flatten
234
+
235
+ { role: role, types: types }
236
+ end.compact
237
+ end
238
+
136
239
  private def enum_instance_methods
137
240
  # @type var methods: Array[String]
138
241
  methods = []
@@ -233,28 +336,36 @@ module RbsRails
233
336
  next unless body_node.type == :block
234
337
 
235
338
  args = args_to_type(body_node.children[1])
236
- "def #{singleton ? 'self.' : ''}#{name}: (#{args}) -> #{relation_class_name}"
339
+ "def #{singleton ? 'self.' : ''}#{name}: #{args} -> #{relation_class_name}"
237
340
  end.compact.join("\n")
238
341
  end
239
342
 
240
343
  private def args_to_type(args_node)
241
344
  # @type var res: Array[String]
242
345
  res = []
346
+ # @type var block: String?
347
+ block = nil
243
348
  args_node.children.each do |node|
244
349
  case node.type
245
350
  when :arg
246
- res << "untyped"
351
+ res << "untyped `#{node.children[0]}`"
247
352
  when :optarg
248
- res << "?untyped"
353
+ res << "?untyped `#{node.children[0]}`"
249
354
  when :kwarg
250
355
  res << "#{node.children[0]}: untyped"
251
356
  when :kwoptarg
252
357
  res << "?#{node.children[0]}: untyped"
358
+ when :restarg
359
+ res << "*untyped `#{node.children[0]}`"
360
+ when :kwrestarg
361
+ res << "**untyped `#{node.children[0]}`"
362
+ when :blockarg
363
+ block = " { (*untyped) -> untyped }"
253
364
  else
254
365
  raise "unexpected: #{node}"
255
366
  end
256
367
  end
257
- res.join(", ")
368
+ "(#{res.join(", ")})#{block}"
258
369
  end
259
370
 
260
371
  private def parse_model_file
@@ -271,7 +382,7 @@ module RbsRails
271
382
  end
272
383
 
273
384
  private def traverse(node, &block)
274
- return to_enum(__method__, node) unless block_given?
385
+ return to_enum(__method__ || raise, node) unless block_given?
275
386
 
276
387
  # @type var block: ^(Parser::AST::Node) -> untyped
277
388
  block.call node
@@ -302,6 +413,12 @@ module RbsRails
302
413
  def #{col.name}_previously_changed?: () -> bool
303
414
  def #{col.name}_previous_change: () -> Array[#{class_name_opt}]?
304
415
  def #{col.name}_previously_was: () -> #{class_name_opt}
416
+ def #{col.name}_before_last_save: () -> #{class_name_opt}
417
+ def #{col.name}_change_to_be_saved: () -> Array[#{class_name_opt}]?
418
+ def #{col.name}_in_database: () -> #{class_name_opt}
419
+ def saved_change_to_#{col.name}: () -> Array[#{class_name_opt}]?
420
+ def saved_change_to_#{col.name}?: () -> bool
421
+ def will_save_change_to_#{col.name}?: () -> bool
305
422
  def restore_#{col.name}!: () -> void
306
423
  def clear_#{col.name}_change: () -> void
307
424
  EOS
@@ -14,7 +14,6 @@ module RbsRails
14
14
 
15
15
  setup_signature_root_dir!
16
16
 
17
- def_copy_signature_files
18
17
  def_generate_rbs_for_models
19
18
  def_generate_rbs_for_path_helpers
20
19
  def_all
@@ -23,19 +22,10 @@ module RbsRails
23
22
  def def_all
24
23
  desc 'Run all tasks of rbs_rails'
25
24
 
26
- deps = [:"#{name}:copy_signature_files", :"#{name}:generate_rbs_for_models", :"#{name}:generate_rbs_for_path_helpers"]
25
+ deps = [:"#{name}:generate_rbs_for_models", :"#{name}:generate_rbs_for_path_helpers"]
27
26
  task("#{name}:all": deps)
28
27
  end
29
28
 
30
- def def_copy_signature_files
31
- desc 'Copy RBS files for rbs_rails'
32
- task("#{name}:copy_signature_files": :environment) do
33
- require 'rbs_rails'
34
-
35
- RbsRails.copy_signatures(to: signature_root_dir)
36
- end
37
- end
38
-
39
29
  def def_generate_rbs_for_models
40
30
  desc 'Generate RBS files for Active Record models'
41
31
  task("#{name}:generate_rbs_for_models": :environment) do
@@ -45,9 +35,8 @@ module RbsRails
45
35
 
46
36
  dep_builder = DependencyBuilder.new
47
37
 
48
- # HACK: for steep
49
- (_ = ::ActiveRecord::Base).descendants.each do |klass|
50
- next if klass.abstract_class?
38
+ ::ActiveRecord::Base.descendants.each do |klass|
39
+ next unless RbsRails::ActiveRecord.generatable?(klass)
51
40
  next if ignore_model_if&.call(klass)
52
41
 
53
42
  path = signature_root_dir / "app/models/#{klass.name.underscore}.rbs"
@@ -2,5 +2,5 @@ module RbsRails
2
2
  # Because of copy_signatures is defined by lib/rbs_rails.rb
3
3
  # @dynamic self.copy_signatures
4
4
 
5
- VERSION = "0.7.0"
5
+ VERSION = "0.9.0"
6
6
  end