rbs_rails 0.7.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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