railties 7.1.3.4 → 8.0.1

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 (193) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -775
  3. data/lib/minitest/rails_plugin.rb +6 -3
  4. data/lib/rails/all.rb +1 -3
  5. data/lib/rails/api/task.rb +6 -4
  6. data/lib/rails/application/bootstrap.rb +5 -7
  7. data/lib/rails/application/configuration.rb +81 -43
  8. data/lib/rails/application/default_middleware_stack.rb +4 -0
  9. data/lib/rails/application/dummy_config.rb +2 -2
  10. data/lib/rails/application/finisher.rb +9 -3
  11. data/lib/rails/application/routes_reloader.rb +16 -2
  12. data/lib/rails/application.rb +27 -86
  13. data/lib/rails/backtrace_cleaner.rb +19 -4
  14. data/lib/rails/cli.rb +0 -1
  15. data/lib/rails/code_statistics.rb +128 -86
  16. data/lib/rails/code_statistics_calculator.rb +78 -76
  17. data/lib/rails/command/helpers/editor.rb +1 -1
  18. data/lib/rails/command.rb +0 -6
  19. data/lib/rails/commands/app/update_command.rb +94 -0
  20. data/lib/rails/commands/boot/boot_command.rb +14 -0
  21. data/lib/rails/commands/console/console_command.rb +2 -21
  22. data/lib/rails/commands/console/irb_console.rb +128 -0
  23. data/lib/rails/commands/credentials/USAGE +4 -4
  24. data/lib/rails/commands/credentials/credentials_command.rb +7 -3
  25. data/lib/rails/commands/dbconsole/dbconsole_command.rb +21 -30
  26. data/lib/rails/commands/dev/dev_command.rb +1 -1
  27. data/lib/rails/commands/devcontainer/devcontainer_command.rb +40 -0
  28. data/lib/rails/commands/rake/rake_command.rb +1 -1
  29. data/lib/rails/commands/runner/runner_command.rb +14 -3
  30. data/lib/rails/commands/server/server_command.rb +5 -3
  31. data/lib/rails/commands/stats/stats_command.rb +19 -0
  32. data/lib/rails/commands/test/test_command.rb +2 -0
  33. data/lib/rails/configuration.rb +10 -1
  34. data/lib/rails/console/methods.rb +7 -0
  35. data/lib/rails/dev_caching.rb +2 -2
  36. data/lib/rails/engine/configuration.rb +3 -1
  37. data/lib/rails/engine/lazy_route_set.rb +114 -0
  38. data/lib/rails/engine.rb +16 -12
  39. data/lib/rails/gem_version.rb +4 -4
  40. data/lib/rails/generators/actions.rb +3 -3
  41. data/lib/rails/generators/app_base.rb +115 -68
  42. data/lib/rails/generators/base.rb +1 -1
  43. data/lib/rails/generators/database.rb +263 -71
  44. data/lib/rails/generators/erb/authentication/authentication_generator.rb +15 -0
  45. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/edit.html.erb +9 -0
  46. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/new.html.erb +8 -0
  47. data/lib/rails/generators/erb/authentication/templates/app/views/sessions/new.html.erb +11 -0
  48. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  49. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  50. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  51. data/lib/rails/generators/generated_attribute.rb +42 -12
  52. data/lib/rails/generators/migration.rb +3 -3
  53. data/lib/rails/generators/rails/app/app_generator.rb +75 -54
  54. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +33 -17
  55. data/lib/rails/generators/rails/app/templates/Gemfile.tt +38 -23
  56. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +6 -11
  57. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  58. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +17 -3
  59. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  60. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  61. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  62. data/lib/rails/generators/rails/app/templates/bin/dev.tt +1 -0
  63. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  64. data/lib/rails/generators/rails/app/templates/bin/setup.tt +6 -5
  65. data/lib/rails/generators/rails/app/templates/bin/thrust.tt +4 -0
  66. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +1 -1
  67. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +26 -3
  68. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +30 -0
  69. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +47 -0
  70. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +26 -3
  71. data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +128 -0
  72. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +22 -26
  73. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +36 -48
  74. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +7 -18
  75. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +0 -7
  76. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  77. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +30 -0
  78. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +35 -27
  79. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +6 -0
  80. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +7 -1
  81. data/lib/rails/generators/rails/app/templates/dockerignore.tt +20 -2
  82. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +144 -0
  83. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  84. data/lib/rails/generators/rails/app/templates/gitignore.tt +4 -5
  85. data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +17 -0
  86. data/lib/rails/generators/rails/app/templates/public/400.html +114 -0
  87. data/lib/rails/generators/rails/app/templates/public/404.html +113 -66
  88. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +114 -0
  89. data/lib/rails/generators/rails/app/templates/public/422.html +113 -66
  90. data/lib/rails/generators/rails/app/templates/public/500.html +113 -65
  91. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  92. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  93. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  94. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  95. data/lib/rails/generators/rails/authentication/USAGE +6 -0
  96. data/lib/rails/generators/rails/authentication/authentication_generator.rb +58 -0
  97. data/lib/rails/generators/rails/authentication/templates/app/channels/application_cable/connection.rb.tt +16 -0
  98. data/lib/rails/generators/rails/authentication/templates/app/controllers/concerns/authentication.rb.tt +52 -0
  99. data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +33 -0
  100. data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +21 -0
  101. data/lib/rails/generators/rails/authentication/templates/app/mailers/passwords_mailer.rb.tt +6 -0
  102. data/lib/rails/generators/rails/authentication/templates/app/models/current.rb.tt +4 -0
  103. data/lib/rails/generators/rails/authentication/templates/app/models/session.rb.tt +3 -0
  104. data/lib/rails/generators/rails/authentication/templates/app/models/user.rb.tt +6 -0
  105. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +4 -0
  106. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +2 -0
  107. data/lib/rails/generators/rails/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt +7 -0
  108. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
  109. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +4 -0
  110. data/lib/rails/generators/rails/db/system/change/change_generator.rb +132 -21
  111. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +176 -0
  112. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  113. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  114. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  115. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  116. data/lib/rails/generators/rails/plugin/plugin_generator.rb +47 -16
  117. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  118. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +6 -2
  119. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  120. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  121. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  122. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  123. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  124. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  125. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -2
  126. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
  127. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +3 -3
  128. data/lib/rails/generators/rails/script/USAGE +18 -0
  129. data/lib/rails/generators/rails/script/script_generator.rb +18 -0
  130. data/lib/rails/generators/rails/script/templates/script.rb.tt +3 -0
  131. data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +14 -0
  132. data/lib/rails/generators/test_unit/authentication/templates/test/fixtures/users.yml.tt +9 -0
  133. data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +7 -0
  134. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  135. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  136. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +15 -1
  137. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  138. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  139. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  140. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  141. data/lib/rails/generators/testing/assertions.rb +20 -0
  142. data/lib/rails/generators/testing/behavior.rb +7 -6
  143. data/lib/rails/generators.rb +7 -2
  144. data/lib/rails/health_controller.rb +1 -1
  145. data/lib/rails/info.rb +2 -2
  146. data/lib/rails/info_controller.rb +10 -2
  147. data/lib/rails/mailers_controller.rb +14 -1
  148. data/lib/rails/paths.rb +2 -2
  149. data/lib/rails/pwa_controller.rb +15 -0
  150. data/lib/rails/rack/logger.rb +15 -7
  151. data/lib/rails/rack/silence_request.rb +33 -0
  152. data/lib/rails/rack.rb +1 -0
  153. data/lib/rails/railtie/configurable.rb +2 -2
  154. data/lib/rails/railtie.rb +15 -16
  155. data/lib/rails/source_annotation_extractor.rb +31 -14
  156. data/lib/rails/tasks/framework.rake +0 -26
  157. data/lib/rails/tasks/statistics.rake +13 -28
  158. data/lib/rails/tasks/tmp.rake +1 -1
  159. data/lib/rails/templates/layouts/application.html.erb +1 -1
  160. data/lib/rails/templates/rails/info/notes.html.erb +65 -0
  161. data/lib/rails/templates/rails/mailers/email.html.erb +12 -8
  162. data/lib/rails/templates/rails/welcome/index.html.erb +4 -2
  163. data/lib/rails/test_help.rb +2 -4
  164. data/lib/rails/test_unit/reporter.rb +8 -2
  165. data/lib/rails/test_unit/runner.rb +27 -2
  166. data/lib/rails/test_unit/test_parser.rb +48 -0
  167. data/lib/rails.rb +7 -4
  168. metadata +77 -45
  169. data/lib/rails/app_updater.rb +0 -40
  170. data/lib/rails/commands/secrets/USAGE +0 -61
  171. data/lib/rails/commands/secrets/secrets_command.rb +0 -47
  172. data/lib/rails/console/app.rb +0 -35
  173. data/lib/rails/console/helpers.rb +0 -19
  174. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -2
  175. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt +0 -4
  176. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt +0 -4
  177. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  178. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +0 -54
  179. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  180. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  181. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  182. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  183. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +0 -284
  184. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +0 -13
  185. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  186. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  187. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  188. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +0 -13
  189. data/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt +0 -10
  190. data/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt +0 -6
  191. data/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt +0 -17
  192. data/lib/rails/ruby_version_check.rb +0 -17
  193. data/lib/rails/secrets.rb +0 -110
@@ -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([(/thrust/ if skip_thruster?), (/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"
@@ -130,10 +142,8 @@ module Rails
130
142
  active_storage_config_exist = File.exist?("config/storage.yml")
131
143
  rack_cors_config_exist = File.exist?("config/initializers/cors.rb")
132
144
  assets_config_exist = File.exist?("config/initializers/assets.rb")
133
- asset_manifest_exist = File.exist?("app/assets/config/manifest.js")
134
145
  asset_app_stylesheet_exist = File.exist?("app/assets/stylesheets/application.css")
135
146
  csp_config_exist = File.exist?("config/initializers/content_security_policy.rb")
136
- permissions_policy_config_exist = File.exist?("config/initializers/permissions_policy.rb")
137
147
 
138
148
  @config_target_version = Rails.application.config.loaded_config_version || "5.0"
139
149
 
@@ -147,15 +157,11 @@ module Rails
147
157
  template "config/storage.yml"
148
158
  end
149
159
 
150
- if skip_sprockets? && skip_propshaft? && !assets_config_exist
160
+ if skip_asset_pipeline? && !assets_config_exist
151
161
  remove_file "config/initializers/assets.rb"
152
162
  end
153
163
 
154
- if skip_sprockets? && !asset_manifest_exist
155
- remove_file "app/assets/config/manifest.js"
156
- end
157
-
158
- if skip_sprockets? && !asset_app_stylesheet_exist
164
+ if skip_asset_pipeline? && !asset_app_stylesheet_exist
159
165
  remove_file "app/assets/stylesheets/application.css"
160
166
  end
161
167
 
@@ -167,10 +173,6 @@ module Rails
167
173
  unless csp_config_exist
168
174
  remove_file "config/initializers/content_security_policy.rb"
169
175
  end
170
-
171
- unless permissions_policy_config_exist
172
- remove_file "config/initializers/permissions_policy.rb"
173
- end
174
176
  end
175
177
  end
176
178
 
@@ -199,7 +201,7 @@ module Rails
199
201
  end
200
202
 
201
203
  def database_yml
202
- template "config/databases/#{options[:database]}.yml", "config/database.yml"
204
+ template database.template, "config/database.yml"
203
205
  end
204
206
 
205
207
  def db
@@ -209,7 +211,6 @@ module Rails
209
211
  def lib
210
212
  empty_directory "lib"
211
213
  empty_directory_with_keep_file "lib/tasks"
212
- empty_directory_with_keep_file "lib/assets"
213
214
  end
214
215
 
215
216
  def log
@@ -217,9 +218,15 @@ module Rails
217
218
  end
218
219
 
219
220
  def public_directory
221
+ return if options[:update] && options[:api]
222
+
220
223
  directory "public", "public", recursive: false
221
224
  end
222
225
 
226
+ def script
227
+ empty_directory_with_keep_file "script"
228
+ end
229
+
223
230
  def storage
224
231
  empty_directory_with_keep_file "storage"
225
232
  empty_directory_with_keep_file "tmp/storage"
@@ -233,7 +240,6 @@ module Rails
233
240
  empty_directory_with_keep_file "test/helpers"
234
241
  empty_directory_with_keep_file "test/integration"
235
242
 
236
- template "test/channels/application_cable/connection_test.rb"
237
243
  template "test/test_helper.rb"
238
244
  end
239
245
 
@@ -246,8 +252,6 @@ module Rails
246
252
  def tmp
247
253
  empty_directory_with_keep_file "tmp"
248
254
  empty_directory_with_keep_file "tmp/pids"
249
- empty_directory "tmp/cache"
250
- empty_directory "tmp/cache/assets"
251
255
  end
252
256
 
253
257
  def vendor
@@ -255,15 +259,27 @@ module Rails
255
259
  end
256
260
 
257
261
  def config_target_version
258
- defined?(@config_target_version) ? @config_target_version : Rails::VERSION::STRING.to_f
262
+ @config_target_version || Rails::VERSION::STRING.to_f
263
+ end
264
+
265
+ def devcontainer
266
+ devcontainer_options = {
267
+ database: options[:database],
268
+ redis: options[:skip_solid] && !(options[:skip_action_cable] && options[:skip_active_job]),
269
+ kamal: !options[:skip_kamal],
270
+ system_test: depends_on_system_test?,
271
+ active_storage: !options[:skip_active_storage],
272
+ dev: options[:dev],
273
+ node: using_node?,
274
+ app_name: app_name,
275
+ skip_solid: options[:skip_solid]
276
+ }
277
+
278
+ Rails::Generators::DevcontainerGenerator.new([], devcontainer_options).invoke_all
259
279
  end
260
280
  end
261
281
 
262
282
  module Generators
263
- # We need to store the RAILS_DEV_PATH in a constant, otherwise the path
264
- # can change in Ruby 1.8.7 when we FileUtils.cd.
265
- RAILS_DEV_PATH = File.expand_path("../../../../../..", __dir__)
266
-
267
283
  class AppGenerator < AppBase
268
284
  # :stopdoc:
269
285
 
@@ -273,8 +289,8 @@ module Rails
273
289
  class_option :version, type: :boolean, aliases: "-v", group: :rails, desc: "Show Rails version number and quit"
274
290
  class_option :api, type: :boolean, desc: "Preconfigure smaller stack for API only apps"
275
291
  class_option :minimal, type: :boolean, desc: "Preconfigure a minimal rails app"
276
- class_option :javascript, type: :string, aliases: ["-j", "--js"], default: "importmap", desc: "Choose JavaScript approach [options: importmap (default), bun, webpack, esbuild, rollup]"
277
- 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"
292
+ class_option :javascript, type: :string, aliases: ["-j", "--js"], default: "importmap", enum: JAVASCRIPT_OPTIONS, desc: "Choose JavaScript approach"
293
+ class_option :css, type: :string, aliases: "-c", enum: CSS_OPTIONS, desc: "Choose CSS processor. Check https://github.com/rails/cssbundling-rails for more options"
278
294
  class_option :skip_bundle, type: :boolean, aliases: "-B", default: nil, desc: "Don't run bundle install"
279
295
  class_option :skip_decrypted_diffs, type: :boolean, default: nil, desc: "Don't configure git to show decrypted diffs of encrypted credentials"
280
296
 
@@ -318,10 +334,6 @@ module Rails
318
334
 
319
335
  imply_options(OPTION_IMPLICATIONS, meta_options: META_OPTIONS)
320
336
 
321
- if !options[:skip_active_record] && !DATABASES.include?(options[:database])
322
- raise Error, "Invalid value for --database option. Supported preconfigurations are: #{DATABASES.join(", ")}."
323
- end
324
-
325
337
  @after_bundle_callbacks = []
326
338
  end
327
339
 
@@ -371,6 +383,16 @@ module Rails
371
383
  build(:dockerfiles)
372
384
  end
373
385
 
386
+ def create_rubocop_file
387
+ return if skip_rubocop?
388
+ build(:rubocop)
389
+ end
390
+
391
+ def create_cifiles
392
+ return if skip_ci?
393
+ build(:cifiles)
394
+ end
395
+
374
396
  def create_config_files
375
397
  build(:config)
376
398
  end
@@ -389,11 +411,6 @@ module Rails
389
411
  build(:credentials_diff_enroll)
390
412
  end
391
413
 
392
- def display_upgrade_guide_info
393
- say "\nAfter this, check Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html for more details about upgrading your app."
394
- end
395
- remove_task :display_upgrade_guide_info
396
-
397
414
  def create_boot_file
398
415
  template "config/boot.rb"
399
416
  end
@@ -420,6 +437,11 @@ module Rails
420
437
  build(:public_directory)
421
438
  end
422
439
 
440
+ def create_script_folder
441
+ return if options[:dummy_app]
442
+ build(:script)
443
+ end
444
+
423
445
  def create_tmp_files
424
446
  build(:tmp)
425
447
  end
@@ -437,14 +459,17 @@ module Rails
437
459
  end
438
460
 
439
461
  def create_storage_files
440
- build(:storage)
462
+ build(:storage) unless skip_storage?
463
+ end
464
+
465
+ def create_devcontainer_files
466
+ return if skip_devcontainer? || options[:dummy_app]
467
+ build(:devcontainer)
441
468
  end
442
469
 
443
470
  def delete_app_assets_if_api_option
444
471
  if options[:api]
445
472
  remove_dir "app/assets"
446
- remove_dir "lib/assets"
447
- remove_dir "tmp/cache/assets"
448
473
  end
449
474
  end
450
475
 
@@ -461,29 +486,26 @@ module Rails
461
486
  remove_dir "app/views"
462
487
  else
463
488
  remove_file "app/views/layouts/application.html.erb"
489
+ remove_dir "app/views/pwa"
464
490
  end
465
491
  end
466
492
  end
467
493
 
468
494
  def delete_public_files_if_api_option
469
495
  if options[:api]
496
+ remove_file "public/400.html"
470
497
  remove_file "public/404.html"
498
+ remove_file "public/406-unsupported-browser.html"
471
499
  remove_file "public/422.html"
472
500
  remove_file "public/500.html"
473
- remove_file "public/apple-touch-icon-precomposed.png"
474
- remove_file "public/apple-touch-icon.png"
475
- remove_file "public/favicon.ico"
501
+ remove_file "public/icon.png"
502
+ remove_file "public/icon.svg"
476
503
  end
477
504
  end
478
505
 
479
- def delete_assets_initializer_skipping_sprockets_and_propshaft
480
- if skip_sprockets? && skip_propshaft?
506
+ def delete_assets_initializer_skipping_asset_pipeline
507
+ if skip_asset_pipeline?
481
508
  remove_file "config/initializers/assets.rb"
482
- end
483
-
484
- if skip_sprockets?
485
- remove_file "app/assets/config/manifest.js"
486
- remove_dir "app/assets/config"
487
509
  remove_file "app/assets/stylesheets/application.css"
488
510
  create_file "app/assets/stylesheets/application.css", "/* Application styles */\n" unless options[:api]
489
511
  end
@@ -513,15 +535,12 @@ module Rails
513
535
  def delete_action_cable_files_skipping_action_cable
514
536
  if options[:skip_action_cable]
515
537
  remove_dir "app/javascript/channels"
516
- remove_dir "app/channels"
517
- remove_dir "test/channels"
518
538
  end
519
539
  end
520
540
 
521
541
  def delete_non_api_initializers_if_api_option
522
542
  if options[:api]
523
543
  remove_file "config/initializers/content_security_policy.rb"
524
- remove_file "config/initializers/permissions_policy.rb"
525
544
  end
526
545
  end
527
546
 
@@ -548,6 +567,8 @@ module Rails
548
567
  public_task :run_javascript
549
568
  public_task :run_hotwire
550
569
  public_task :run_css
570
+ public_task :run_kamal
571
+ public_task :run_solid
551
572
 
552
573
  def run_after_bundle_callbacks
553
574
  @after_bundle_callbacks.each(&:call)
@@ -644,7 +665,7 @@ module Rails
644
665
  end
645
666
 
646
667
  def read_rc_file(railsrc)
647
- extra_args = File.readlines(railsrc).flat_map(&:split)
668
+ extra_args = File.readlines(railsrc).flat_map.each { |line| line.split("#", 2).first.split }
648
669
  puts "Using #{extra_args.join(" ")} from #{railsrc}"
649
670
  extra_args
650
671
  end
@@ -1,25 +1,37 @@
1
- # syntax = docker/dockerfile:1
1
+ # syntax=docker/dockerfile:1
2
+ # check=error=true
2
3
 
3
- # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
4
- ARG RUBY_VERSION=<%= gem_ruby_version %>
5
- FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
4
+ # This Dockerfile is designed for production, not development. Use with Kamal or build'n'run by hand:
5
+ # docker build -t <%= app_name %> .
6
+ # docker run -d -p 80:<%= skip_thruster? ? 3000 : 80 %> -e RAILS_MASTER_KEY=<value from config/master.key> --name <%= app_name %> <%= app_name %>
7
+
8
+ # For a containerized dev environment, see Dev Containers: https://guides.rubyonrails.org/getting_started_with_devcontainer.html
9
+
10
+ # Make sure RUBY_VERSION matches the Ruby version in .ruby-version
11
+ ARG RUBY_VERSION=<%= Gem.ruby_version %>
12
+ FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
6
13
 
7
14
  # Rails app lives here
8
15
  WORKDIR /rails
9
16
 
17
+ # Install base packages
18
+ RUN apt-get update -qq && \
19
+ apt-get install --no-install-recommends -y <%= dockerfile_base_packages.join(" ") %> && \
20
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives
21
+
10
22
  # Set production environment
11
23
  ENV RAILS_ENV="production" \
12
24
  BUNDLE_DEPLOYMENT="1" \
13
25
  BUNDLE_PATH="/usr/local/bundle" \
14
26
  BUNDLE_WITHOUT="development"
15
27
 
16
-
17
28
  # Throw-away build stage to reduce size of final image
18
- FROM base as build
29
+ FROM base AS build
19
30
 
20
31
  # Install packages needed to build gems<%= using_node? ? " and node modules" : "" %>
21
32
  RUN apt-get update -qq && \
22
- apt-get install --no-install-recommends -y <%= dockerfile_build_packages.join(" ") %>
33
+ apt-get install --no-install-recommends -y <%= dockerfile_build_packages.join(" ") %> && \
34
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives
23
35
 
24
36
  <% if using_node? -%>
25
37
  # Install JavaScript dependencies
@@ -76,28 +88,32 @@ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
76
88
 
77
89
  <% end -%>
78
90
 
91
+ <% if using_node? -%>
92
+ RUN rm -rf node_modules
93
+ <% end %>
94
+
79
95
  # Final stage for app image
80
96
  FROM base
81
97
 
82
- <% unless dockerfile_deploy_packages.empty? -%>
83
- # Install packages needed for deployment
84
- RUN apt-get update -qq && \
85
- apt-get install --no-install-recommends -y <%= dockerfile_deploy_packages.join(" ") %> && \
86
- rm -rf /var/lib/apt/lists /var/cache/apt/archives
87
-
88
- <% end -%>
89
98
  # Copy built artifacts: gems, application
90
- COPY --from=build /usr/local/bundle /usr/local/bundle
99
+ COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
91
100
  COPY --from=build /rails /rails
92
101
 
93
102
  # Run and own only the runtime files as a non-root user for security
94
- RUN useradd rails --create-home --shell /bin/bash && \
103
+ RUN groupadd --system --gid 1000 rails && \
104
+ useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
95
105
  chown -R rails:rails <%= dockerfile_chown_directories.join(" ") %>
96
- USER rails:rails
106
+ USER 1000:1000
97
107
 
98
108
  # Entrypoint prepares the database.
99
109
  ENTRYPOINT ["/rails/bin/docker-entrypoint"]
100
110
 
111
+ <% if skip_thruster? -%>
101
112
  # Start the server by default, this can be overwritten at runtime
102
113
  EXPOSE 3000
103
114
  CMD ["./bin/rails", "server"]
115
+ <% else -%>
116
+ # Start server via Thruster by default, this can be overwritten at runtime
117
+ EXPOSE 80
118
+ CMD ["./bin/thrust", "./bin/rails", "server"]
119
+ <% end -%>
@@ -1,26 +1,44 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- ruby <%= "\"#{gem_ruby_version}\"" -%>
4
-
5
- <% gemfile_entries.each do |gemfile_entry| %>
3
+ <% gemfile_entries.each do |gemfile_entry| -%>
6
4
  <%= gemfile_entry %>
7
5
  <% end -%>
8
6
  <% unless options.minimal? -%>
9
7
 
10
- # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
11
- # gem "kredis"
12
-
13
8
  # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
14
9
  # gem "bcrypt", "~> 3.1.7"
15
10
  <% end -%>
16
11
 
17
12
  # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
18
- gem "tzinfo-data", platforms: %i[ <%= bundler_windows_platforms %> jruby ]
13
+ gem "tzinfo-data", platforms: %i[ windows jruby ]
14
+ <% unless options.skip_solid? -%>
15
+
16
+ <% if options.skip_action_cable? -%>
17
+ # Use the database-backed adapters for Rails.cache and Active Job
18
+ <% else -%>
19
+ # Use the database-backed adapters for Rails.cache, Active Job, and Action Cable
20
+ <% end -%>
21
+ gem "solid_cache"
22
+ gem "solid_queue"
23
+ <% unless options.skip_action_cable? -%>
24
+ gem "solid_cable"
25
+ <% end -%>
26
+ <% end -%>
19
27
  <% if depend_on_bootsnap? -%>
20
28
 
21
29
  # Reduces boot times through caching; required in config/boot.rb
22
30
  gem "bootsnap", require: false
23
31
  <% end -%>
32
+ <% unless options.skip_kamal? -%>
33
+
34
+ # Deploy this application anywhere as a Docker container [https://kamal-deploy.org]
35
+ gem "kamal", require: false
36
+ <% end -%>
37
+ <% unless options.skip_thruster? -%>
38
+
39
+ # Add HTTP asset caching/compression and X-Sendfile acceleration to Puma [https://github.com/basecamp/thruster/]
40
+ gem "thruster", require: false
41
+ <% end -%>
24
42
  <% unless skip_active_storage? -%>
25
43
 
26
44
  # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
@@ -35,34 +53,31 @@ gem "bootsnap", require: false
35
53
 
36
54
  group :development, :test do
37
55
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
38
- gem "debug", platforms: %i[ mri <%= bundler_windows_platforms %> ]
56
+ gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
57
+ <%- unless options.skip_brakeman? -%>
58
+
59
+ # Static analysis for security vulnerabilities [https://brakemanscanner.org/]
60
+ gem "brakeman", require: false
61
+ <%- end -%>
62
+ <%- unless options.skip_rubocop? -%>
63
+
64
+ # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]
65
+ gem "rubocop-rails-omakase", require: false
66
+ <%- end -%>
39
67
  end
40
68
  <% end -%>
41
69
 
42
- group :development do
43
70
  <%- unless options.api? || options.skip_dev_gems? -%>
71
+ group :development do
44
72
  # Use console on exceptions pages [https://github.com/rails/web-console]
45
73
  gem "web-console"
46
-
47
- # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
48
- # gem "rack-mini-profiler"
49
-
50
- <%- end -%>
51
- # Speed up commands on slow machines / big apps [https://github.com/rails/spring]
52
- # gem "spring"
53
- <%- if RUBY_VERSION >= "3.1" && RUBY_VERSION < "3.2" -%>
54
-
55
- gem "error_highlight", ">= 0.4.0", platforms: [:ruby]
56
- <%- end -%>
57
74
  end
75
+ <%- end -%>
58
76
 
59
77
  <%- if depends_on_system_test? -%>
60
78
  group :test do
61
79
  # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
62
80
  gem "capybara"
63
81
  gem "selenium-webdriver"
64
- <%- if RUBY_VERSION < "3.0" -%>
65
- gem "webdrivers"
66
- <%- end -%>
67
82
  end
68
83
  <%- end -%>
@@ -1,15 +1,10 @@
1
1
  /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
2
+ * This is a manifest file that'll be compiled into application.css.
4
3
  *
5
- * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
6
- * vendor/assets/stylesheets directory can be referenced here using a relative path.
4
+ * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
5
+ * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
6
+ * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
7
+ * depending on specificity.
7
8
  *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
9
+ * Consider organizing styles into separate files for maintainability.
15
10
  */
@@ -1,2 +1,6 @@
1
1
  class ApplicationController < ActionController::<%= options.api? ? "API" : "Base" %>
2
+ <%- unless options.api? -%>
3
+ # Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
4
+ allow_browser versions: :modern
5
+ <% end -%>
2
6
  end
@@ -1,15 +1,29 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title><%= camelized %></title>
4
+ <title><%%= content_for(:title) || "<%= app_name.titleize %>" %></title>
5
5
  <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <meta name="apple-mobile-web-app-capable" content="yes">
7
+ <meta name="mobile-web-app-capable" content="yes">
6
8
  <%%= csrf_meta_tags %>
7
9
  <%%= csp_meta_tag %>
8
10
 
11
+ <%%= yield :head %>
12
+
13
+ <%%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
14
+ <%%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
15
+
16
+ <link rel="icon" href="/icon.png" type="image/png">
17
+ <link rel="icon" href="/icon.svg" type="image/svg+xml">
18
+ <link rel="apple-touch-icon" href="/icon.png">
19
+
20
+ <%- style_link_target = options[:skip_asset_pipeline] ? "\"application\"" : ":app" -%>
9
21
  <%- if options[:skip_hotwire] || options[:skip_javascript] -%>
10
- <%%= stylesheet_link_tag "application" %>
22
+ <%%# Includes all stylesheet files in app/assets/stylesheets %>
23
+ <%%= stylesheet_link_tag <%= style_link_target %> %>
11
24
  <%- else -%>
12
- <%%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
25
+ <%%# Includes all stylesheet files in app/assets/stylesheets %>
26
+ <%%= stylesheet_link_tag <%= style_link_target %>, "data-turbo-track": "reload" %>
13
27
  <%- end -%>
14
28
  </head>
15
29
 
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "<%= camelized %>",
3
+ "icons": [
4
+ {
5
+ "src": "/icon.png",
6
+ "type": "image/png",
7
+ "sizes": "512x512"
8
+ },
9
+ {
10
+ "src": "/icon.png",
11
+ "type": "image/png",
12
+ "sizes": "512x512",
13
+ "purpose": "maskable"
14
+ }
15
+ ],
16
+ "start_url": "/",
17
+ "display": "standalone",
18
+ "scope": "/",
19
+ "description": "<%= camelized %>.",
20
+ "theme_color": "red",
21
+ "background_color": "red"
22
+ }
@@ -0,0 +1,26 @@
1
+ // Add a service worker for processing Web Push notifications:
2
+ //
3
+ // self.addEventListener("push", async (event) => {
4
+ // const { title, options } = await event.data.json()
5
+ // event.waitUntil(self.registration.showNotification(title, options))
6
+ // })
7
+ //
8
+ // self.addEventListener("notificationclick", function(event) {
9
+ // event.notification.close()
10
+ // event.waitUntil(
11
+ // clients.matchAll({ type: "window" }).then((clientList) => {
12
+ // for (let i = 0; i < clientList.length; i++) {
13
+ // let client = clientList[i]
14
+ // let clientPath = (new URL(client.url)).pathname
15
+ //
16
+ // if (clientPath == event.notification.data.path && "focus" in client) {
17
+ // return client.focus()
18
+ // }
19
+ // }
20
+ //
21
+ // if (clients.openWindow) {
22
+ // return clients.openWindow(event.notification.data.path)
23
+ // }
24
+ // })
25
+ // )
26
+ // })
@@ -0,0 +1,6 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ ARGV.unshift("--ensure-latest")
5
+
6
+ load Gem.bin_path("brakeman", "brakeman")
@@ -0,0 +1 @@
1
+ exec "./bin/rails", "server", *ARGV
@@ -0,0 +1,7 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ # explicit rubocop config increases performance slightly while avoiding config confusion.
5
+ ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__))
6
+
7
+ load Gem.bin_path("rubocop", "rubocop")