railties 7.1.0 → 7.2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +203 -650
  3. data/lib/minitest/rails_plugin.rb +5 -2
  4. data/lib/rails/all.rb +1 -3
  5. data/lib/rails/api/task.rb +6 -4
  6. data/lib/rails/application/bootstrap.rb +11 -8
  7. data/lib/rails/application/configuration.rb +80 -36
  8. data/lib/rails/application/dummy_config.rb +2 -2
  9. data/lib/rails/application/finisher.rb +10 -0
  10. data/lib/rails/application.rb +29 -76
  11. data/lib/rails/backtrace_cleaner.rb +18 -3
  12. data/lib/rails/cli.rb +0 -1
  13. data/lib/rails/command.rb +1 -1
  14. data/lib/rails/commands/app/update_command.rb +102 -0
  15. data/lib/rails/commands/boot/boot_command.rb +14 -0
  16. data/lib/rails/commands/console/console_command.rb +2 -21
  17. data/lib/rails/commands/console/irb_console.rb +146 -0
  18. data/lib/rails/commands/credentials/USAGE +1 -1
  19. data/lib/rails/commands/credentials/credentials_command.rb +2 -2
  20. data/lib/rails/commands/dbconsole/dbconsole_command.rb +21 -30
  21. data/lib/rails/commands/devcontainer/devcontainer_command.rb +39 -0
  22. data/lib/rails/commands/rake/rake_command.rb +1 -1
  23. data/lib/rails/commands/runner/runner_command.rb +14 -3
  24. data/lib/rails/commands/server/server_command.rb +5 -3
  25. data/lib/rails/commands/test/test_command.rb +2 -0
  26. data/lib/rails/configuration.rb +10 -1
  27. data/lib/rails/console/app.rb +5 -32
  28. data/lib/rails/console/helpers.rb +5 -16
  29. data/lib/rails/console/methods.rb +23 -0
  30. data/lib/rails/engine/configuration.rb +45 -6
  31. data/lib/rails/engine.rb +24 -17
  32. data/lib/rails/gem_version.rb +3 -3
  33. data/lib/rails/generators/active_model.rb +26 -12
  34. data/lib/rails/generators/app_base.rb +80 -61
  35. data/lib/rails/generators/base.rb +9 -5
  36. data/lib/rails/generators/database.rb +227 -69
  37. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  38. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  39. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  40. data/lib/rails/generators/generated_attribute.rb +26 -1
  41. data/lib/rails/generators/migration.rb +3 -3
  42. data/lib/rails/generators/rails/app/app_generator.rb +57 -32
  43. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +23 -16
  44. data/lib/rails/generators/rails/app/templates/Gemfile.tt +17 -17
  45. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  46. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +8 -1
  47. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  48. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  49. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  50. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  51. data/lib/rails/generators/rails/app/templates/bin/setup.tt +6 -2
  52. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +1 -1
  53. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  54. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +11 -4
  55. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +8 -1
  56. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +3 -3
  57. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +14 -7
  58. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +14 -6
  59. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +10 -7
  60. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +1 -1
  61. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +3 -3
  62. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +70 -0
  63. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +25 -26
  64. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +6 -0
  65. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +5 -0
  66. data/lib/rails/generators/rails/app/templates/dockerignore.tt +13 -0
  67. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +138 -0
  68. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  69. data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -3
  70. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +66 -0
  71. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  72. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  73. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  74. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  75. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
  76. data/lib/rails/generators/rails/db/system/change/change_generator.rb +134 -20
  77. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +166 -0
  78. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  79. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  80. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  81. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  82. data/lib/rails/generators/rails/plugin/plugin_generator.rb +40 -7
  83. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  84. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +5 -1
  85. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  86. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  87. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  88. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  89. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  90. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  91. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -2
  92. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  93. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  94. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +15 -1
  95. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  96. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  97. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  98. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  99. data/lib/rails/generators/testing/assertions.rb +20 -0
  100. data/lib/rails/generators/testing/behavior.rb +7 -6
  101. data/lib/rails/generators.rb +7 -3
  102. data/lib/rails/health_controller.rb +2 -2
  103. data/lib/rails/info.rb +2 -2
  104. data/lib/rails/info_controller.rb +4 -2
  105. data/lib/rails/mailers_controller.rb +14 -1
  106. data/lib/rails/paths.rb +2 -2
  107. data/lib/rails/pwa_controller.rb +15 -0
  108. data/lib/rails/rack/logger.rb +15 -7
  109. data/lib/rails/railtie/configurable.rb +2 -2
  110. data/lib/rails/railtie.rb +15 -16
  111. data/lib/rails/tasks/framework.rake +0 -26
  112. data/lib/rails/tasks/tmp.rake +1 -1
  113. data/lib/rails/tasks/zeitwerk.rake +14 -34
  114. data/lib/rails/templates/layouts/application.html.erb +1 -1
  115. data/lib/rails/templates/rails/mailers/email.html.erb +20 -9
  116. data/lib/rails/templates/rails/welcome/index.html.erb +4 -2
  117. data/lib/rails/test_help.rb +2 -4
  118. data/lib/rails/test_unit/reporter.rb +8 -2
  119. data/lib/rails/test_unit/runner.rb +26 -2
  120. data/lib/rails/test_unit/test_parser.rb +45 -0
  121. data/lib/rails/testing/maintain_test_schema.rb +1 -1
  122. data/lib/rails/zeitwerk_checker.rb +15 -0
  123. data/lib/rails.rb +7 -4
  124. metadata +46 -35
  125. data/lib/rails/app_updater.rb +0 -40
  126. data/lib/rails/commands/secrets/USAGE +0 -61
  127. data/lib/rails/commands/secrets/secrets_command.rb +0 -46
  128. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  129. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +0 -54
  130. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  131. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  132. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  133. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  134. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +0 -223
  135. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  136. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  137. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  138. data/lib/rails/ruby_version_check.rb +0 -17
  139. data/lib/rails/secrets.rb +0 -110
@@ -2,83 +2,76 @@
2
2
 
3
3
  module Rails
4
4
  module Generators
5
- module Database # :nodoc:
6
- JDBC_DATABASES = %w( jdbcmysql jdbcsqlite3 jdbcpostgresql jdbc )
7
- DATABASES = %w( mysql trilogy postgresql sqlite3 oracle sqlserver ) + JDBC_DATABASES
8
-
9
- def initialize(*)
10
- super
11
- convert_database_option_for_jruby
12
- end
13
-
14
- def gem_for_database(database = options[:database])
15
- case database
16
- when "mysql" then ["mysql2", ["~> 0.5"]]
17
- when "trilogy" then ["trilogy", ["~> 2.4"]]
18
- when "postgresql" then ["pg", ["~> 1.1"]]
19
- when "sqlite3" then ["sqlite3", ["~> 1.4"]]
20
- when "oracle" then ["activerecord-oracle_enhanced-adapter", nil]
21
- when "sqlserver" then ["activerecord-sqlserver-adapter", nil]
22
- when "jdbcmysql" then ["activerecord-jdbcmysql-adapter", nil]
23
- when "jdbcsqlite3" then ["activerecord-jdbcsqlite3-adapter", nil]
24
- when "jdbcpostgresql" then ["activerecord-jdbcpostgresql-adapter", nil]
25
- when "jdbc" then ["activerecord-jdbc-adapter", nil]
26
- else [database, nil]
27
- end
28
- end
29
-
30
- def docker_for_database_build(database = options[:database])
31
- case database
32
- when "mysql" then "build-essential default-libmysqlclient-dev git"
33
- when "trilogy" then "build-essential default-libmysqlclient-dev git"
34
- when "postgresql" then "build-essential git libpq-dev"
35
- when "sqlite3" then "build-essential git"
36
- else nil
37
- end
38
- end
39
-
40
- def docker_for_database_deploy(database = options[:database])
41
- case database
42
- when "mysql" then "curl default-mysql-client libvips"
43
- when "trilogy" then "curl default-mysql-client libvips"
44
- when "postgresql" then "curl libvips postgresql-client"
45
- when "sqlite3" then "curl libsqlite3-0 libvips"
46
- else nil
47
- end
48
- end
49
-
50
- def convert_database_option_for_jruby
51
- if defined?(JRUBY_VERSION)
52
- opt = options.dup
53
- case opt[:database]
54
- when "postgresql" then opt[:database] = "jdbcpostgresql"
55
- when "mysql" then opt[:database] = "jdbcmysql"
56
- when "sqlite3" then opt[:database] = "jdbcsqlite3"
5
+ class Database
6
+ DATABASES = %w( mysql trilogy postgresql sqlite3 )
7
+
8
+ class << self
9
+ def build(database_name)
10
+ case database_name
11
+ when "mysql" then MySQL.new
12
+ when "postgresql" then PostgreSQL.new
13
+ when "trilogy" then MariaDB.new
14
+ when "sqlite3" then SQLite3.new
15
+ else Null.new
57
16
  end
58
- self.options = opt.freeze
59
17
  end
60
- end
61
18
 
62
- def build_package_for_database(database = options[:database])
63
- case database
64
- when "mysql" then "default-libmysqlclient-dev"
65
- when "postgresql" then "libpq-dev"
66
- else nil
19
+ def all
20
+ @all ||= [
21
+ MySQL.new,
22
+ PostgreSQL.new,
23
+ MariaDB.new,
24
+ SQLite3.new,
25
+ ]
67
26
  end
68
27
  end
69
28
 
70
- def deploy_package_for_database(database = options[:database])
71
- case database
72
- when "mysql" then "default-mysql-client"
73
- when "postgresql" then "postgresql-client"
74
- when "sqlite3" then "libsqlite3-0"
75
- else nil
76
- end
29
+ def name
30
+ raise NotImplementedError
31
+ end
32
+
33
+ def service
34
+ raise NotImplementedError
35
+ end
36
+
37
+ def port
38
+ raise NotImplementedError
39
+ end
40
+
41
+ def feature_name
42
+ raise NotImplementedError
77
43
  end
78
44
 
79
- private
80
- def mysql_socket
81
- @mysql_socket ||= [
45
+ def gem
46
+ raise NotImplementedError
47
+ end
48
+
49
+ def base_package
50
+ raise NotImplementedError
51
+ end
52
+
53
+ def build_package
54
+ raise NotImplementedError
55
+ end
56
+
57
+ def socket; end
58
+ def host; end
59
+
60
+ def feature
61
+ return unless feature_name
62
+
63
+ { feature_name => {} }
64
+ end
65
+
66
+ def volume
67
+ return unless service
68
+
69
+ "#{name}-data"
70
+ end
71
+
72
+ module MySqlSocket
73
+ def socket
74
+ @socket ||= [
82
75
  "/tmp/mysql.sock", # default
83
76
  "/var/run/mysqld/mysqld.sock", # debian/gentoo
84
77
  "/var/tmp/mysql.sock", # freebsd
@@ -90,6 +83,171 @@ module Rails
90
83
  "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
91
84
  ].find { |f| File.exist?(f) } unless Gem.win_platform?
92
85
  end
86
+
87
+ def host
88
+ "localhost"
89
+ end
90
+ end
91
+
92
+ class MySQL < Database
93
+ include MySqlSocket
94
+
95
+ def name
96
+ "mysql"
97
+ end
98
+
99
+ def service
100
+ {
101
+ "image" => "mysql/mysql-server:8.0",
102
+ "restart" => "unless-stopped",
103
+ "environment" => {
104
+ "MYSQL_ALLOW_EMPTY_PASSWORD" => "true",
105
+ "MYSQL_ROOT_HOST" => "%"
106
+ },
107
+ "volumes" => ["mysql-data:/var/lib/mysql"],
108
+ "networks" => ["default"],
109
+ }
110
+ end
111
+
112
+ def port
113
+ 3306
114
+ end
115
+
116
+ def gem
117
+ ["mysql2", ["~> 0.5"]]
118
+ end
119
+
120
+ def base_package
121
+ "default-mysql-client"
122
+ end
123
+
124
+ def build_package
125
+ "default-libmysqlclient-dev"
126
+ end
127
+
128
+ def feature_name
129
+ "ghcr.io/rails/devcontainer/features/mysql-client"
130
+ end
131
+ end
132
+
133
+ class PostgreSQL < Database
134
+ def name
135
+ "postgres"
136
+ end
137
+
138
+ def service
139
+ {
140
+ "image" => "postgres:16.1",
141
+ "restart" => "unless-stopped",
142
+ "networks" => ["default"],
143
+ "volumes" => ["postgres-data:/var/lib/postgresql/data"],
144
+ "environment" => {
145
+ "POSTGRES_USER" => "postgres",
146
+ "POSTGRES_PASSWORD" => "postgres"
147
+ }
148
+ }
149
+ end
150
+
151
+ def port
152
+ 5432
153
+ end
154
+
155
+ def gem
156
+ ["pg", ["~> 1.1"]]
157
+ end
158
+
159
+ def base_package
160
+ "postgresql-client"
161
+ end
162
+
163
+ def build_package
164
+ "libpq-dev"
165
+ end
166
+
167
+ def feature_name
168
+ "ghcr.io/rails/devcontainer/features/postgres-client"
169
+ end
170
+ end
171
+
172
+ class MariaDB < Database
173
+ include MySqlSocket
174
+
175
+ def name
176
+ "mariadb"
177
+ end
178
+
179
+ def service
180
+ {
181
+ "image" => "mariadb:10.5",
182
+ "restart" => "unless-stopped",
183
+ "networks" => ["default"],
184
+ "volumes" => ["mariadb-data:/var/lib/mysql"],
185
+ "environment" => {
186
+ "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" => "true",
187
+ },
188
+ }
189
+ end
190
+
191
+ def port
192
+ 3306
193
+ end
194
+
195
+ def gem
196
+ ["trilogy", ["~> 2.7"]]
197
+ end
198
+
199
+ def base_package
200
+ nil
201
+ end
202
+
203
+ def build_package
204
+ nil
205
+ end
206
+
207
+ def feature_name
208
+ nil
209
+ end
210
+ end
211
+
212
+ class SQLite3 < Database
213
+ def name
214
+ "sqlite3"
215
+ end
216
+
217
+ def service
218
+ nil
219
+ end
220
+
221
+ def port
222
+ nil
223
+ end
224
+
225
+ def gem
226
+ ["sqlite3", [">= 1.4"]]
227
+ end
228
+
229
+ def base_package
230
+ "sqlite3"
231
+ end
232
+
233
+ def build_package
234
+ nil
235
+ end
236
+
237
+ def feature_name
238
+ "ghcr.io/rails/devcontainer/features/sqlite3"
239
+ end
240
+ end
241
+
242
+ class Null < Database
243
+ def name; end
244
+ def service; end
245
+ def port; end
246
+ def volume; end
247
+ def base_package; end
248
+ def build_package; end
249
+ def feature_name; end
250
+ end
93
251
  end
94
252
  end
95
253
  end
@@ -1,3 +1,5 @@
1
+ <%% content_for :title, "Editing <%= human_name.downcase %>" %>
2
+
1
3
  <h1>Editing <%= human_name.downcase %></h1>
2
4
 
3
5
  <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
@@ -1,5 +1,7 @@
1
1
  <p style="color: green"><%%= notice %></p>
2
2
 
3
+ <%% content_for :title, "<%= human_name.pluralize %>" %>
4
+
3
5
  <h1><%= human_name.pluralize %></h1>
4
6
 
5
7
  <div id="<%= plural_table_name %>">
@@ -1,3 +1,5 @@
1
+ <%% content_for :title, "New <%= human_name.downcase %>" %>
2
+
1
3
  <h1>New <%= human_name.downcase %></h1>
2
4
 
3
5
  <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
@@ -72,7 +72,7 @@ module Rails
72
72
  def valid_type?(type)
73
73
  DEFAULT_TYPES.include?(type.to_s) ||
74
74
  !defined?(ActiveRecord::Base) ||
75
- ActiveRecord::Base.connection.valid_type?(type)
75
+ ActiveRecord::Base.lease_connection.valid_type?(type)
76
76
  end
77
77
 
78
78
  def valid_index_type?(index_type)
@@ -239,6 +239,31 @@ module Rails
239
239
  end
240
240
  end
241
241
  end
242
+
243
+ def to_s
244
+ if has_uniq_index?
245
+ "#{name}:#{type}#{print_attribute_options}:uniq"
246
+ elsif has_index?
247
+ "#{name}:#{type}#{print_attribute_options}:index"
248
+ else
249
+ "#{name}:#{type}#{print_attribute_options}"
250
+ end
251
+ end
252
+
253
+ private
254
+ def print_attribute_options
255
+ if attr_options.empty?
256
+ ""
257
+ elsif attr_options[:size]
258
+ "{#{attr_options[:size]}}"
259
+ elsif attr_options[:limit]
260
+ "{#{attr_options[:limit]}}"
261
+ elsif attr_options[:precision] && attr_options[:scale]
262
+ "{#{attr_options[:precision]},#{attr_options[:scale]}}"
263
+ else
264
+ "{#{attr_options.keys.join(",")}}"
265
+ end
266
+ end
242
267
  end
243
268
  end
244
269
  end
@@ -7,7 +7,7 @@ module Rails
7
7
  module Generators
8
8
  # Holds common methods for migrations. It assumes that migrations have the
9
9
  # [0-9]*_name format and can be used by other frameworks (like Sequel)
10
- # just by implementing the next migration version method.
10
+ # just by implementing the +next_migration_number+ method.
11
11
  module Migration
12
12
  extend ActiveSupport::Concern
13
13
  attr_reader :migration_number, :migration_file_name, :migration_class_name
@@ -46,10 +46,10 @@ module Rails
46
46
  end
47
47
 
48
48
  # Creates a migration template at the given destination. The difference
49
- # to the default template method is that the migration version is appended
49
+ # to the default template method is that the migration number is prepended
50
50
  # to the destination file name.
51
51
  #
52
- # The migration version, migration file name, migration class name are
52
+ # The migration number, migration file name, migration class name are
53
53
  # available as instance variables in the template to be rendered.
54
54
  #
55
55
  # migration_template "migration.rb", "db/migrate/add_foo_to_bar.rb"
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails/generators/app_base"
4
+ require "rails/generators/rails/devcontainer/devcontainer_generator"
4
5
 
5
6
  module Rails
6
7
  module ActionMethods # :nodoc:
@@ -15,8 +16,8 @@ module Rails
15
16
  %w(template copy_file directory empty_directory inside
16
17
  empty_directory_with_keep_file create_file chmod shebang).each do |method|
17
18
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
18
- def #{method}(*args, &block)
19
- @generator.send(:#{method}, *args, &block)
19
+ def #{method}(...)
20
+ @generator.send(:#{method}, ...)
20
21
  end
21
22
  RUBY
22
23
  end
@@ -82,6 +83,16 @@ module Rails
82
83
  chmod "bin/docker-entrypoint", 0755 & ~File.umask, verbose: false
83
84
  end
84
85
 
86
+ def cifiles
87
+ empty_directory ".github/workflows"
88
+ template "github/ci.yml", ".github/workflows/ci.yml"
89
+ template "github/dependabot.yml", ".github/dependabot.yml"
90
+ end
91
+
92
+ def rubocop
93
+ template "rubocop.yml", ".rubocop.yml"
94
+ end
95
+
85
96
  def version_control
86
97
  if !options[:skip_git] && !options[:pretend]
87
98
  run git_init_command, capture: options[:quiet], abort_on_failure: false
@@ -98,7 +109,8 @@ module Rails
98
109
  end
99
110
 
100
111
  def bin
101
- directory "bin" do |content|
112
+ exclude_pattern = Regexp.union([(/rubocop/ if skip_rubocop?), (/brakeman/ if skip_brakeman?)].compact)
113
+ directory "bin", { exclude_pattern: exclude_pattern } do |content|
102
114
  "#{shebang}\n" + content
103
115
  end
104
116
  chmod "bin", 0755 & ~File.umask, verbose: false
@@ -116,7 +128,7 @@ module Rails
116
128
  template "application.rb"
117
129
  template "environment.rb"
118
130
  template "cable.yml" unless options[:update] || options[:skip_action_cable]
119
- template "puma.rb" unless options[:update]
131
+ template "puma.rb"
120
132
  template "storage.yml" unless options[:update] || skip_active_storage?
121
133
 
122
134
  directory "environments"
@@ -172,10 +184,6 @@ module Rails
172
184
  remove_file "config/initializers/permissions_policy.rb"
173
185
  end
174
186
  end
175
-
176
- if !skip_sprockets?
177
- insert_into_file "config/application.rb", %(require "sprockets/railtie"), after: /require\(["']rails\/all["']\)\n/
178
- end
179
187
  end
180
188
 
181
189
  def master_key
@@ -221,6 +229,8 @@ module Rails
221
229
  end
222
230
 
223
231
  def public_directory
232
+ return if options[:update] && options[:api]
233
+
224
234
  directory "public", "public", recursive: false
225
235
  end
226
236
 
@@ -250,8 +260,6 @@ module Rails
250
260
  def tmp
251
261
  empty_directory_with_keep_file "tmp"
252
262
  empty_directory_with_keep_file "tmp/pids"
253
- empty_directory "tmp/cache"
254
- empty_directory "tmp/cache/assets"
255
263
  end
256
264
 
257
265
  def vendor
@@ -259,15 +267,25 @@ module Rails
259
267
  end
260
268
 
261
269
  def config_target_version
262
- defined?(@config_target_version) ? @config_target_version : Rails::VERSION::STRING.to_f
270
+ @config_target_version || Rails::VERSION::STRING.to_f
271
+ end
272
+
273
+ def devcontainer
274
+ devcontainer_options = {
275
+ database: options[:database],
276
+ redis: !(options[:skip_action_cable] && options[:skip_active_job]),
277
+ system_test: depends_on_system_test?,
278
+ active_storage: !options[:skip_active_storage],
279
+ dev: options[:dev],
280
+ node: using_node?,
281
+ app_name: app_name
282
+ }
283
+
284
+ Rails::Generators::DevcontainerGenerator.new([], devcontainer_options).invoke_all
263
285
  end
264
286
  end
265
287
 
266
288
  module Generators
267
- # We need to store the RAILS_DEV_PATH in a constant, otherwise the path
268
- # can change in Ruby 1.8.7 when we FileUtils.cd.
269
- RAILS_DEV_PATH = File.expand_path("../../../../../..", __dir__)
270
-
271
289
  class AppGenerator < AppBase
272
290
  # :stopdoc:
273
291
 
@@ -277,8 +295,8 @@ module Rails
277
295
  class_option :version, type: :boolean, aliases: "-v", group: :rails, desc: "Show Rails version number and quit"
278
296
  class_option :api, type: :boolean, desc: "Preconfigure smaller stack for API only apps"
279
297
  class_option :minimal, type: :boolean, desc: "Preconfigure a minimal rails app"
280
- class_option :javascript, type: :string, aliases: ["-j", "--js"], default: "importmap", desc: "Choose JavaScript approach [options: importmap (default), bun, webpack, esbuild, rollup]"
281
- class_option :css, type: :string, aliases: "-c", desc: "Choose CSS processor [options: tailwind, bootstrap, bulma, postcss, sass] check https://github.com/rails/cssbundling-rails for more options"
298
+ class_option :javascript, type: :string, aliases: ["-j", "--js"], default: "importmap", enum: JAVASCRIPT_OPTIONS, desc: "Choose JavaScript approach"
299
+ class_option :css, type: :string, aliases: "-c", enum: CSS_OPTIONS, desc: "Choose CSS processor. Check https://github.com/rails/cssbundling-rails for more options"
282
300
  class_option :skip_bundle, type: :boolean, aliases: "-B", default: nil, desc: "Don't run bundle install"
283
301
  class_option :skip_decrypted_diffs, type: :boolean, default: nil, desc: "Don't configure git to show decrypted diffs of encrypted credentials"
284
302
 
@@ -322,10 +340,6 @@ module Rails
322
340
 
323
341
  imply_options(OPTION_IMPLICATIONS, meta_options: META_OPTIONS)
324
342
 
325
- if !options[:skip_active_record] && !DATABASES.include?(options[:database])
326
- raise Error, "Invalid value for --database option. Supported preconfigurations are: #{DATABASES.join(", ")}."
327
- end
328
-
329
343
  @after_bundle_callbacks = []
330
344
  end
331
345
 
@@ -375,6 +389,16 @@ module Rails
375
389
  build(:dockerfiles)
376
390
  end
377
391
 
392
+ def create_rubocop_file
393
+ return if skip_rubocop?
394
+ build(:rubocop)
395
+ end
396
+
397
+ def create_cifiles
398
+ return if skip_ci?
399
+ build(:cifiles)
400
+ end
401
+
378
402
  def create_config_files
379
403
  build(:config)
380
404
  end
@@ -393,11 +417,6 @@ module Rails
393
417
  build(:credentials_diff_enroll)
394
418
  end
395
419
 
396
- def display_upgrade_guide_info
397
- say "\nAfter this, check Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html for more details about upgrading your app."
398
- end
399
- remove_task :display_upgrade_guide_info
400
-
401
420
  def create_boot_file
402
421
  template "config/boot.rb"
403
422
  end
@@ -441,14 +460,18 @@ module Rails
441
460
  end
442
461
 
443
462
  def create_storage_files
444
- build(:storage)
463
+ build(:storage) unless skip_storage?
464
+ end
465
+
466
+ def create_devcontainer_files
467
+ return if skip_devcontainer? || options[:dummy_app]
468
+ build(:devcontainer)
445
469
  end
446
470
 
447
471
  def delete_app_assets_if_api_option
448
472
  if options[:api]
449
473
  remove_dir "app/assets"
450
474
  remove_dir "lib/assets"
451
- remove_dir "tmp/cache/assets"
452
475
  end
453
476
  end
454
477
 
@@ -465,6 +488,7 @@ module Rails
465
488
  remove_dir "app/views"
466
489
  else
467
490
  remove_file "app/views/layouts/application.html.erb"
491
+ remove_dir "app/views/pwa"
468
492
  end
469
493
  end
470
494
  end
@@ -472,11 +496,11 @@ module Rails
472
496
  def delete_public_files_if_api_option
473
497
  if options[:api]
474
498
  remove_file "public/404.html"
499
+ remove_file "public/406-unsupported-browser.html"
475
500
  remove_file "public/422.html"
476
501
  remove_file "public/500.html"
477
- remove_file "public/apple-touch-icon-precomposed.png"
478
- remove_file "public/apple-touch-icon.png"
479
- remove_file "public/favicon.ico"
502
+ remove_file "public/icon.png"
503
+ remove_file "public/icon.svg"
480
504
  end
481
505
  end
482
506
 
@@ -547,6 +571,7 @@ module Rails
547
571
 
548
572
  public_task :apply_rails_template
549
573
  public_task :run_bundle
574
+ public_task :add_bundler_platforms
550
575
  public_task :generate_bundler_binstub
551
576
  public_task :run_javascript
552
577
  public_task :run_hotwire
@@ -647,7 +672,7 @@ module Rails
647
672
  end
648
673
 
649
674
  def read_rc_file(railsrc)
650
- extra_args = File.readlines(railsrc).flat_map(&:split)
675
+ extra_args = File.readlines(railsrc).flat_map.each { |line| line.split("#", 2).first.split }
651
676
  puts "Using #{extra_args.join(" ")} from #{railsrc}"
652
677
  extra_args
653
678
  end