railties 7.0.8.7 → 7.2.2.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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +210 -272
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.md +99 -0
  5. data/README.rdoc +4 -4
  6. data/lib/minitest/rails_plugin.rb +67 -1
  7. data/lib/rails/all.rb +1 -3
  8. data/lib/rails/api/task.rb +39 -6
  9. data/lib/rails/application/bootstrap.rb +28 -10
  10. data/lib/rails/application/configuration.rb +228 -72
  11. data/lib/rails/application/default_middleware_stack.rb +8 -2
  12. data/lib/rails/application/dummy_config.rb +19 -0
  13. data/lib/rails/application/finisher.rb +50 -33
  14. data/lib/rails/application.rb +117 -76
  15. data/lib/rails/backtrace_cleaner.rb +19 -4
  16. data/lib/rails/cli.rb +5 -3
  17. data/lib/rails/command/actions.rb +10 -12
  18. data/lib/rails/command/base.rb +55 -53
  19. data/lib/rails/command/environment_argument.rb +32 -16
  20. data/lib/rails/command/helpers/editor.rb +17 -12
  21. data/lib/rails/command.rb +84 -33
  22. data/lib/rails/commands/about/about_command.rb +14 -0
  23. data/lib/rails/commands/app/update_command.rb +102 -0
  24. data/lib/rails/commands/application/application_command.rb +2 -0
  25. data/lib/rails/commands/boot/boot_command.rb +14 -0
  26. data/lib/rails/commands/console/console_command.rb +11 -30
  27. data/lib/rails/commands/console/irb_console.rb +146 -0
  28. data/lib/rails/commands/credentials/USAGE +53 -55
  29. data/lib/rails/commands/credentials/credentials_command/diffing.rb +5 -3
  30. data/lib/rails/commands/credentials/credentials_command.rb +64 -70
  31. data/lib/rails/commands/db/system/change/change_command.rb +2 -1
  32. data/lib/rails/commands/dbconsole/dbconsole_command.rb +32 -131
  33. data/lib/rails/commands/destroy/destroy_command.rb +3 -2
  34. data/lib/rails/commands/dev/dev_command.rb +1 -6
  35. data/lib/rails/commands/devcontainer/devcontainer_command.rb +39 -0
  36. data/lib/rails/commands/encrypted/USAGE +15 -20
  37. data/lib/rails/commands/encrypted/encrypted_command.rb +46 -35
  38. data/lib/rails/commands/gem_help/USAGE +16 -0
  39. data/lib/rails/commands/gem_help/gem_help_command.rb +13 -0
  40. data/lib/rails/commands/generate/generate_command.rb +2 -2
  41. data/lib/rails/commands/help/USAGE +13 -13
  42. data/lib/rails/commands/help/help_command.rb +21 -2
  43. data/lib/rails/commands/initializers/initializers_command.rb +1 -4
  44. data/lib/rails/commands/middleware/middleware_command.rb +17 -0
  45. data/lib/rails/commands/new/new_command.rb +2 -0
  46. data/lib/rails/commands/notes/notes_command.rb +2 -1
  47. data/lib/rails/commands/plugin/plugin_command.rb +2 -0
  48. data/lib/rails/commands/rake/rake_command.rb +25 -22
  49. data/lib/rails/commands/restart/restart_command.rb +14 -0
  50. data/lib/rails/commands/routes/routes_command.rb +13 -1
  51. data/lib/rails/commands/runner/USAGE +14 -12
  52. data/lib/rails/commands/runner/runner_command.rb +42 -19
  53. data/lib/rails/commands/secret/secret_command.rb +13 -0
  54. data/lib/rails/commands/server/server_command.rb +37 -34
  55. data/lib/rails/commands/test/USAGE +14 -0
  56. data/lib/rails/commands/test/test_command.rb +58 -14
  57. data/lib/rails/commands/unused_routes/unused_routes_command.rb +75 -0
  58. data/lib/rails/commands/version/version_command.rb +1 -0
  59. data/lib/rails/configuration.rb +15 -6
  60. data/lib/rails/console/app.rb +5 -35
  61. data/lib/rails/console/helpers.rb +5 -16
  62. data/lib/rails/console/methods.rb +23 -0
  63. data/lib/rails/deprecator.rb +7 -0
  64. data/lib/rails/engine/configuration.rb +50 -6
  65. data/lib/rails/engine.rb +53 -25
  66. data/lib/rails/gem_version.rb +4 -4
  67. data/lib/rails/generators/actions.rb +6 -15
  68. data/lib/rails/generators/active_model.rb +28 -14
  69. data/lib/rails/generators/app_base.rb +382 -88
  70. data/lib/rails/generators/app_name.rb +3 -14
  71. data/lib/rails/generators/base.rb +21 -9
  72. data/lib/rails/generators/database.rb +231 -35
  73. data/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt +1 -1
  74. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  75. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  76. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  77. data/lib/rails/generators/generated_attribute.rb +38 -1
  78. data/lib/rails/generators/migration.rb +4 -5
  79. data/lib/rails/generators/model_helpers.rb +2 -1
  80. data/lib/rails/generators/rails/app/USAGE +22 -6
  81. data/lib/rails/generators/rails/app/app_generator.rb +135 -86
  82. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +110 -0
  83. data/lib/rails/generators/rails/app/templates/Gemfile.tt +19 -21
  84. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  85. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +8 -1
  86. data/lib/rails/generators/rails/app/templates/app/views/layouts/mailer.html.erb.tt +1 -1
  87. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  88. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  89. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  90. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  91. data/lib/rails/generators/rails/app/templates/bin/setup.tt +15 -2
  92. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +6 -17
  93. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  94. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +11 -6
  95. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +10 -3
  96. data/lib/rails/generators/rails/app/templates/config/databases/{jdbcmysql.yml.tt → trilogy.yml.tt} +12 -7
  97. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +25 -8
  98. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +40 -28
  99. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +20 -13
  100. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +3 -1
  101. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +2 -2
  102. data/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt +1 -1
  103. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +4 -4
  104. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +70 -0
  105. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +11 -9
  106. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +11 -13
  107. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +25 -34
  108. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +11 -1
  109. data/lib/rails/generators/rails/app/templates/db/seeds.rb.tt +6 -4
  110. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +15 -0
  111. data/lib/rails/generators/rails/app/templates/dockerignore.tt +56 -0
  112. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +138 -0
  113. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  114. data/lib/rails/generators/rails/app/templates/gitignore.tt +7 -11
  115. data/lib/rails/generators/rails/app/templates/node-version.tt +1 -0
  116. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +66 -0
  117. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  118. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  119. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  120. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  121. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +10 -8
  122. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +9 -7
  123. data/lib/rails/generators/rails/application_record/application_record_generator.rb +4 -0
  124. data/lib/rails/generators/rails/benchmark/benchmark_generator.rb +2 -1
  125. data/lib/rails/generators/rails/controller/USAGE +12 -4
  126. data/lib/rails/generators/rails/controller/controller_generator.rb +6 -1
  127. data/lib/rails/generators/rails/controller/templates/controller.rb.tt +1 -1
  128. data/lib/rails/generators/rails/credentials/credentials_generator.rb +29 -24
  129. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +8 -0
  130. data/lib/rails/generators/rails/db/system/change/change_generator.rb +146 -5
  131. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +166 -0
  132. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  133. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  134. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  135. data/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb +1 -2
  136. data/lib/rails/generators/rails/migration/USAGE +21 -11
  137. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  138. data/lib/rails/generators/rails/model/model_generator.rb +4 -0
  139. data/lib/rails/generators/rails/plugin/USAGE +17 -6
  140. data/lib/rails/generators/rails/plugin/plugin_generator.rb +45 -22
  141. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  142. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +7 -3
  143. data/lib/rails/generators/rails/plugin/templates/MIT-LICENSE.tt +1 -1
  144. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  145. data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +1 -17
  146. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  147. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  148. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  149. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +0 -2
  150. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  151. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  152. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +5 -5
  153. data/lib/rails/generators/rails/resource/resource_generator.rb +6 -0
  154. data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +2 -1
  155. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +1 -1
  156. data/lib/rails/generators/test_case.rb +2 -2
  157. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  158. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  159. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +16 -2
  160. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  161. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  162. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  163. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  164. data/lib/rails/generators/testing/assertions.rb +20 -0
  165. data/lib/rails/generators/testing/{behaviour.rb → behavior.rb} +8 -4
  166. data/lib/rails/generators.rb +12 -16
  167. data/lib/rails/health_controller.rb +55 -0
  168. data/lib/rails/info.rb +3 -3
  169. data/lib/rails/info_controller.rb +33 -11
  170. data/lib/rails/mailers_controller.rb +29 -6
  171. data/lib/rails/paths.rb +15 -12
  172. data/lib/rails/pwa_controller.rb +15 -0
  173. data/lib/rails/rack/logger.rb +27 -16
  174. data/lib/rails/rackup/server.rb +15 -0
  175. data/lib/rails/railtie/configurable.rb +2 -2
  176. data/lib/rails/railtie/configuration.rb +14 -1
  177. data/lib/rails/railtie.rb +33 -34
  178. data/lib/rails/source_annotation_extractor.rb +67 -18
  179. data/lib/rails/tasks/engine.rake +8 -8
  180. data/lib/rails/tasks/framework.rake +2 -34
  181. data/lib/rails/tasks/log.rake +1 -1
  182. data/lib/rails/tasks/misc.rake +3 -14
  183. data/lib/rails/tasks/statistics.rake +5 -4
  184. data/lib/rails/tasks/tmp.rake +6 -6
  185. data/lib/rails/tasks/zeitwerk.rake +15 -35
  186. data/lib/rails/tasks.rb +0 -2
  187. data/lib/rails/templates/layouts/application.html.erb +1 -1
  188. data/lib/rails/templates/rails/mailers/email.html.erb +44 -8
  189. data/lib/rails/templates/rails/mailers/index.html.erb +14 -7
  190. data/lib/rails/templates/rails/mailers/mailer.html.erb +11 -5
  191. data/lib/rails/templates/rails/welcome/index.html.erb +5 -2
  192. data/lib/rails/test_help.rb +11 -18
  193. data/lib/rails/test_unit/line_filtering.rb +1 -1
  194. data/lib/rails/test_unit/reporter.rb +14 -4
  195. data/lib/rails/test_unit/runner.rb +62 -20
  196. data/lib/rails/test_unit/test_parser.rb +133 -0
  197. data/lib/rails/test_unit/testing.rake +13 -33
  198. data/lib/rails/testing/maintain_test_schema.rb +16 -0
  199. data/lib/rails/version.rb +1 -1
  200. data/lib/rails/zeitwerk_checker.rb +15 -0
  201. data/lib/rails.rb +20 -17
  202. metadata +87 -40
  203. data/RDOC_MAIN.rdoc +0 -97
  204. data/lib/rails/app_updater.rb +0 -40
  205. data/lib/rails/application/dummy_erb_compiler.rb +0 -18
  206. data/lib/rails/commands/secrets/USAGE +0 -66
  207. data/lib/rails/commands/secrets/secrets_command.rb +0 -65
  208. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  209. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  210. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  211. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  212. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  213. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +0 -143
  214. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  215. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  216. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  217. data/lib/rails/generators/rails/model/USAGE +0 -113
  218. data/lib/rails/ruby_version_check.rb +0 -15
  219. data/lib/rails/secrets.rb +0 -110
  220. data/lib/rails/tasks/middleware.rake +0 -9
  221. data/lib/rails/tasks/restart.rake +0 -9
@@ -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,14 +16,14 @@ 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
23
24
 
24
- def method_missing(meth, *args, &block)
25
- @generator.send(meth, *args, &block)
25
+ def method_missing(...)
26
+ @generator.send(...)
26
27
  end
27
28
  end
28
29
 
@@ -54,6 +55,10 @@ module Rails
54
55
  template "ruby-version", ".ruby-version"
55
56
  end
56
57
 
58
+ def node_version
59
+ template "node-version", ".node-version"
60
+ end
61
+
57
62
  def gemfile
58
63
  template "Gemfile"
59
64
  end
@@ -70,12 +75,27 @@ module Rails
70
75
  template "gitattributes", ".gitattributes"
71
76
  end
72
77
 
78
+ def dockerfiles
79
+ template "Dockerfile"
80
+ template "dockerignore", ".dockerignore"
81
+
82
+ template "docker-entrypoint", "bin/docker-entrypoint"
83
+ chmod "bin/docker-entrypoint", 0755 & ~File.umask, verbose: false
84
+ end
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
+
73
96
  def version_control
74
97
  if !options[:skip_git] && !options[:pretend]
75
- run "git init", capture: options[:quiet], abort_on_failure: false
76
- if user_default_branch.strip.empty?
77
- `git symbolic-ref HEAD refs/heads/main`
78
- end
98
+ run git_init_command, capture: options[:quiet], abort_on_failure: false
79
99
  end
80
100
  end
81
101
 
@@ -89,7 +109,8 @@ module Rails
89
109
  end
90
110
 
91
111
  def bin
92
- 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|
93
114
  "#{shebang}\n" + content
94
115
  end
95
116
  chmod "bin", 0755 & ~File.umask, verbose: false
@@ -103,16 +124,16 @@ module Rails
103
124
  empty_directory "config"
104
125
 
105
126
  inside "config" do
106
- template "routes.rb" unless options[:updating]
127
+ template "routes.rb" unless options[:update]
107
128
  template "application.rb"
108
129
  template "environment.rb"
109
- template "cable.yml" unless options[:updating] || options[:skip_action_cable]
110
- template "puma.rb" unless options[:updating]
111
- template "storage.yml" unless options[:updating] || skip_active_storage?
130
+ template "cable.yml" unless options[:update] || options[:skip_action_cable]
131
+ template "puma.rb"
132
+ template "storage.yml" unless options[:update] || skip_active_storage?
112
133
 
113
134
  directory "environments"
114
135
  directory "initializers"
115
- directory "locales" unless options[:updating]
136
+ directory "locales" unless options[:update]
116
137
  end
117
138
  end
118
139
 
@@ -163,10 +184,6 @@ module Rails
163
184
  remove_file "config/initializers/permissions_policy.rb"
164
185
  end
165
186
  end
166
-
167
- if !skip_sprockets?
168
- insert_into_file "config/application.rb", %(require "sprockets/railtie"), after: /require\(["']rails\/all["']\)\n/
169
- end
170
187
  end
171
188
 
172
189
  def master_key
@@ -182,7 +199,15 @@ module Rails
182
199
  return if options[:pretend] || options[:dummy_app]
183
200
 
184
201
  require "rails/generators/rails/credentials/credentials_generator"
185
- Rails::Generators::CredentialsGenerator.new([], quiet: options[:quiet]).add_credentials_file_silently
202
+ Rails::Generators::CredentialsGenerator.new([], quiet: true).add_credentials_file
203
+ end
204
+
205
+ def credentials_diff_enroll
206
+ return if options[:skip_decrypted_diffs] || options[:dummy_app] || options[:pretend]
207
+
208
+ @generator.shell.mute do
209
+ rails_command "credentials:diff --enroll", inline: true, shell: @generator.shell
210
+ end
186
211
  end
187
212
 
188
213
  def database_yml
@@ -193,14 +218,6 @@ module Rails
193
218
  directory "db"
194
219
  end
195
220
 
196
- def db_when_updating
197
- path = File.expand_path("db/schema.rb", destination_root)
198
-
199
- if File.exist?(path)
200
- gsub_file("db/schema.rb", /ActiveRecord::Schema\.define/, "ActiveRecord::Schema[6.1].define")
201
- end
202
- end
203
-
204
221
  def lib
205
222
  empty_directory "lib"
206
223
  empty_directory_with_keep_file "lib/tasks"
@@ -212,6 +229,8 @@ module Rails
212
229
  end
213
230
 
214
231
  def public_directory
232
+ return if options[:update] && options[:api]
233
+
215
234
  directory "public", "public", recursive: false
216
235
  end
217
236
 
@@ -241,8 +260,6 @@ module Rails
241
260
  def tmp
242
261
  empty_directory_with_keep_file "tmp"
243
262
  empty_directory_with_keep_file "tmp/pids"
244
- empty_directory "tmp/cache"
245
- empty_directory "tmp/cache/assets"
246
263
  end
247
264
 
248
265
  def vendor
@@ -250,20 +267,25 @@ module Rails
250
267
  end
251
268
 
252
269
  def config_target_version
253
- defined?(@config_target_version) ? @config_target_version : Rails::VERSION::STRING.to_f
270
+ @config_target_version || Rails::VERSION::STRING.to_f
254
271
  end
255
272
 
256
- private
257
- def user_default_branch
258
- @user_default_branch ||= `git config init.defaultbranch`
259
- end
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
285
+ end
260
286
  end
261
287
 
262
288
  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
289
  class AppGenerator < AppBase
268
290
  # :stopdoc:
269
291
 
@@ -273,42 +295,55 @@ module Rails
273
295
  class_option :version, type: :boolean, aliases: "-v", group: :rails, desc: "Show Rails version number and quit"
274
296
  class_option :api, type: :boolean, desc: "Preconfigure smaller stack for API only apps"
275
297
  class_option :minimal, type: :boolean, desc: "Preconfigure a minimal rails app"
276
- class_option :javascript, type: :string, aliases: "-j", default: "importmap", desc: "Choose JavaScript approach [options: importmap (default), 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"
278
- class_option :skip_bundle, type: :boolean, aliases: "-B", default: false, desc: "Don't run bundle install"
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"
300
+ class_option :skip_bundle, type: :boolean, aliases: "-B", default: nil, desc: "Don't run bundle install"
301
+ class_option :skip_decrypted_diffs, type: :boolean, default: nil, desc: "Don't configure git to show decrypted diffs of encrypted credentials"
302
+
303
+ OPTION_IMPLICATIONS = # :nodoc:
304
+ AppBase::OPTION_IMPLICATIONS.merge(
305
+ skip_git: [:skip_decrypted_diffs],
306
+ minimal: [
307
+ :skip_action_cable,
308
+ :skip_action_mailbox,
309
+ :skip_action_mailer,
310
+ :skip_action_text,
311
+ :skip_active_job,
312
+ :skip_active_storage,
313
+ :skip_bootsnap,
314
+ :skip_dev_gems,
315
+ :skip_hotwire,
316
+ :skip_javascript,
317
+ :skip_jbuilder,
318
+ :skip_system_test,
319
+ ],
320
+ api: [
321
+ :skip_asset_pipeline,
322
+ :skip_javascript,
323
+ ],
324
+ ) do |option, implications, more_implications|
325
+ implications + more_implications
326
+ end
279
327
 
280
- def initialize(*args)
281
- super
328
+ META_OPTIONS = [:minimal] # :nodoc:
282
329
 
283
- if !options[:skip_active_record] && !DATABASES.include?(options[:database])
284
- raise Error, "Invalid value for --database option. Supported preconfigurations are: #{DATABASES.join(", ")}."
285
- end
330
+ def self.apply_rails_template(template, destination) # :nodoc:
331
+ generator = new([destination], { template: template }, { destination_root: destination })
332
+ generator.set_default_accessors!
333
+ generator.apply_rails_template
334
+ generator.run_bundle
335
+ generator.run_after_bundle_callbacks
336
+ end
286
337
 
287
- # Force sprockets and JavaScript to be skipped when generating API only apps.
288
- # Can't modify options hash as it's frozen by default.
289
- if options[:api]
290
- self.options = options.merge(skip_asset_pipeline: true, skip_javascript: true).freeze
291
- end
338
+ def initialize(*args)
339
+ super
292
340
 
293
- if options[:minimal]
294
- self.options = options.merge(
295
- skip_action_cable: true,
296
- skip_action_mailer: true,
297
- skip_action_mailbox: true,
298
- skip_action_text: true,
299
- skip_active_job: true,
300
- skip_active_storage: true,
301
- skip_bootsnap: true,
302
- skip_dev_gems: true,
303
- skip_javascript: true,
304
- skip_jbuilder: true,
305
- skip_system_test: true,
306
- skip_hotwire: true).freeze
307
- end
341
+ imply_options(OPTION_IMPLICATIONS, meta_options: META_OPTIONS)
308
342
 
309
343
  @after_bundle_callbacks = []
310
344
  end
311
345
 
346
+ public_task :report_implied_options
312
347
  public_task :set_default_accessors!
313
348
  public_task :create_root
314
349
  public_task :target_rails_prerelease
@@ -316,6 +351,7 @@ module Rails
316
351
  def create_root_files
317
352
  build(:readme)
318
353
  build(:rakefile)
354
+ build(:node_version) if using_node?
319
355
  build(:ruby_version)
320
356
  build(:configru)
321
357
 
@@ -341,11 +377,6 @@ module Rails
341
377
  end
342
378
  remove_task :update_bin_files
343
379
 
344
- def update_db_schema
345
- build(:db_when_updating)
346
- end
347
- remove_task :update_db_schema
348
-
349
380
  def update_active_storage
350
381
  unless skip_active_storage?
351
382
  rails_command "active_storage:update", inline: true
@@ -353,6 +384,21 @@ module Rails
353
384
  end
354
385
  remove_task :update_active_storage
355
386
 
387
+ def create_dockerfiles
388
+ return if options[:skip_docker] || options[:dummy_app]
389
+ build(:dockerfiles)
390
+ end
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
+
356
402
  def create_config_files
357
403
  build(:config)
358
404
  end
@@ -368,13 +414,9 @@ module Rails
368
414
 
369
415
  def create_credentials
370
416
  build(:credentials)
417
+ build(:credentials_diff_enroll)
371
418
  end
372
419
 
373
- def display_upgrade_guide_info
374
- say "\nAfter this, check Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html for more details about upgrading your app."
375
- end
376
- remove_task :display_upgrade_guide_info
377
-
378
420
  def create_boot_file
379
421
  template "config/boot.rb"
380
422
  end
@@ -418,14 +460,18 @@ module Rails
418
460
  end
419
461
 
420
462
  def create_storage_files
421
- build(:storage) unless skip_active_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)
422
469
  end
423
470
 
424
471
  def delete_app_assets_if_api_option
425
472
  if options[:api]
426
473
  remove_dir "app/assets"
427
474
  remove_dir "lib/assets"
428
- remove_dir "tmp/cache/assets"
429
475
  end
430
476
  end
431
477
 
@@ -438,10 +484,11 @@ module Rails
438
484
 
439
485
  def delete_app_views_if_api_option
440
486
  if options[:api]
441
- if skip_action_mailer?
487
+ if options[:skip_action_mailer]
442
488
  remove_dir "app/views"
443
489
  else
444
490
  remove_file "app/views/layouts/application.html.erb"
491
+ remove_dir "app/views/pwa"
445
492
  end
446
493
  end
447
494
  end
@@ -449,11 +496,11 @@ module Rails
449
496
  def delete_public_files_if_api_option
450
497
  if options[:api]
451
498
  remove_file "public/404.html"
499
+ remove_file "public/406-unsupported-browser.html"
452
500
  remove_file "public/422.html"
453
501
  remove_file "public/500.html"
454
- remove_file "public/apple-touch-icon-precomposed.png"
455
- remove_file "public/apple-touch-icon.png"
456
- remove_file "public/favicon.ico"
502
+ remove_file "public/icon.png"
503
+ remove_file "public/icon.svg"
457
504
  end
458
505
  end
459
506
 
@@ -483,7 +530,7 @@ module Rails
483
530
  end
484
531
 
485
532
  def delete_action_mailer_files_skipping_action_mailer
486
- if skip_action_mailer?
533
+ if options[:skip_action_mailer]
487
534
  remove_file "app/views/layouts/mailer.html.erb"
488
535
  remove_file "app/views/layouts/mailer.text.erb"
489
536
  remove_dir "app/mailers"
@@ -514,7 +561,7 @@ module Rails
514
561
 
515
562
  def delete_new_framework_defaults
516
563
  unless options[:update]
517
- remove_file "config/initializers/new_framework_defaults_7_0.rb"
564
+ remove_file "config/initializers/new_framework_defaults_#{Rails::VERSION::MAJOR}_#{Rails::VERSION::MINOR}.rb"
518
565
  end
519
566
  end
520
567
 
@@ -522,7 +569,9 @@ module Rails
522
569
  build(:leftovers)
523
570
  end
524
571
 
525
- public_task :apply_rails_template, :run_bundle
572
+ public_task :apply_rails_template
573
+ public_task :run_bundle
574
+ public_task :add_bundler_platforms
526
575
  public_task :generate_bundler_binstub
527
576
  public_task :run_javascript
528
577
  public_task :run_hotwire
@@ -623,7 +672,7 @@ module Rails
623
672
  end
624
673
 
625
674
  def read_rc_file(railsrc)
626
- extra_args = File.readlines(railsrc).flat_map(&:split)
675
+ extra_args = File.readlines(railsrc).flat_map.each { |line| line.split("#", 2).first.split }
627
676
  puts "Using #{extra_args.join(" ")} from #{railsrc}"
628
677
  extra_args
629
678
  end
@@ -0,0 +1,110 @@
1
+ # syntax = docker/dockerfile:1
2
+
3
+ # This Dockerfile is designed for production, not development. Use with Kamal or build'n'run by hand:
4
+ # docker build -t my-app .
5
+ # docker run -d -p 80:80 -p 443:443 --name my-app -e RAILS_MASTER_KEY=<value from config/master.key> my-app
6
+
7
+ # Make sure RUBY_VERSION matches the Ruby version in .ruby-version
8
+ ARG RUBY_VERSION=<%= gem_ruby_version %>
9
+ FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
10
+
11
+ # Rails app lives here
12
+ WORKDIR /rails
13
+
14
+ # Install base packages
15
+ RUN apt-get update -qq && \
16
+ apt-get install --no-install-recommends -y <%= dockerfile_base_packages.join(" ") %> && \
17
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives
18
+
19
+ # Set production environment
20
+ ENV RAILS_ENV="production" \
21
+ BUNDLE_DEPLOYMENT="1" \
22
+ BUNDLE_PATH="/usr/local/bundle" \
23
+ BUNDLE_WITHOUT="development"
24
+
25
+ # Throw-away build stage to reduce size of final image
26
+ FROM base AS build
27
+
28
+ # Install packages needed to build gems<%= using_node? ? " and node modules" : "" %>
29
+ RUN apt-get update -qq && \
30
+ apt-get install --no-install-recommends -y <%= dockerfile_build_packages.join(" ") %> && \
31
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives
32
+
33
+ <% if using_node? -%>
34
+ # Install JavaScript dependencies
35
+ ARG NODE_VERSION=<%= node_version %>
36
+ ARG YARN_VERSION=<%= dockerfile_yarn_version %>
37
+ ENV PATH=/usr/local/node/bin:$PATH
38
+ RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
39
+ /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
40
+ npm install -g yarn@$YARN_VERSION && \
41
+ rm -rf /tmp/node-build-master
42
+
43
+ <% end -%>
44
+ <% if using_bun? -%>
45
+ ENV BUN_INSTALL=/usr/local/bun
46
+ ENV PATH=/usr/local/bun/bin:$PATH
47
+ ARG BUN_VERSION=<%= dockerfile_bun_version %>
48
+ RUN curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"
49
+
50
+ <% end -%>
51
+ # Install application gems
52
+ COPY Gemfile Gemfile.lock ./
53
+ RUN bundle install && \
54
+ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git<% if depend_on_bootsnap? -%> && \
55
+ bundle exec bootsnap precompile --gemfile<% end %>
56
+
57
+ <% if using_node? -%>
58
+ # Install node modules
59
+ COPY package.json yarn.lock ./
60
+ RUN yarn install --frozen-lockfile
61
+
62
+ <% end -%>
63
+ <% if using_bun? -%>
64
+ # Install node modules
65
+ COPY package.json bun.lockb ./
66
+ RUN bun install --frozen-lockfile
67
+
68
+ <% end -%>
69
+ # Copy application code
70
+ COPY . .
71
+
72
+ <% if depend_on_bootsnap? -%>
73
+ # Precompile bootsnap code for faster boot times
74
+ RUN bundle exec bootsnap precompile app/ lib/
75
+
76
+ <% end -%>
77
+ <% unless dockerfile_binfile_fixups.empty? -%>
78
+ # Adjust binfiles to be executable on Linux
79
+ <%= "RUN " + dockerfile_binfile_fixups.join(" && \\\n ") %>
80
+
81
+ <% end -%>
82
+ <% unless options.api? || skip_asset_pipeline? -%>
83
+ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY
84
+ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
85
+
86
+ <% end -%>
87
+
88
+ <% if using_node? -%>
89
+ RUN rm -rf node_modules
90
+ <% end %>
91
+
92
+ # Final stage for app image
93
+ FROM base
94
+
95
+ # Copy built artifacts: gems, application
96
+ COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
97
+ COPY --from=build /rails /rails
98
+
99
+ # Run and own only the runtime files as a non-root user for security
100
+ RUN groupadd --system --gid 1000 rails && \
101
+ useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
102
+ chown -R rails:rails <%= dockerfile_chown_directories.join(" ") %>
103
+ USER 1000:1000
104
+
105
+ # Entrypoint prepares the database.
106
+ ENTRYPOINT ["/rails/bin/docker-entrypoint"]
107
+
108
+ # Start the server by default, this can be overwritten at runtime
109
+ EXPOSE 3000
110
+ CMD ["./bin/rails", "server"]
@@ -1,9 +1,6 @@
1
1
  source "https://rubygems.org"
2
- git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
2
 
4
- ruby <%= "\"#{RUBY_VERSION}\"" -%>
5
-
6
- <% gemfile_entries.each do |gemfile_entry| %>
3
+ <% gemfile_entries.each do |gemfile_entry| -%>
7
4
  <%= gemfile_entry %>
8
5
  <% end -%>
9
6
  <% unless options.minimal? -%>
@@ -16,17 +13,12 @@ ruby <%= "\"#{RUBY_VERSION}\"" -%>
16
13
  <% end -%>
17
14
 
18
15
  # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
19
- gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
16
+ gem "tzinfo-data", platforms: %i[ <%= bundler_windows_platforms %> jruby ]
20
17
  <% if depend_on_bootsnap? -%>
21
18
 
22
19
  # Reduces boot times through caching; required in config/boot.rb
23
20
  gem "bootsnap", require: false
24
21
  <% end -%>
25
- <% unless skip_sprockets? || options.minimal? -%>
26
-
27
- # Use Sass to process CSS
28
- # gem "sassc-rails"
29
- <% end -%>
30
22
  <% unless skip_active_storage? -%>
31
23
 
32
24
  # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
@@ -34,37 +26,43 @@ gem "bootsnap", require: false
34
26
  <% end -%>
35
27
  <%- if options.api? -%>
36
28
 
37
- # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
29
+ # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin Ajax possible
38
30
  # gem "rack-cors"
39
31
  <%- end -%>
40
32
  <% if RUBY_ENGINE == "ruby" -%>
41
33
 
42
34
  group :development, :test do
43
35
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
44
- gem "debug", platforms: %i[ mri mingw x64_mingw ]
36
+ gem "debug", platforms: %i[ mri <%= bundler_windows_platforms %> ], require: "debug/prelude"
37
+ <%- unless options.skip_brakeman? -%>
38
+
39
+ # Static analysis for security vulnerabilities [https://brakemanscanner.org/]
40
+ gem "brakeman", require: false
41
+ <%- end -%>
42
+ <%- unless options.skip_rubocop? -%>
43
+
44
+ # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]
45
+ gem "rubocop-rails-omakase", require: false
46
+ <%- end -%>
45
47
  end
46
48
  <% end -%>
47
49
 
48
- group :development do
49
50
  <%- unless options.api? || options.skip_dev_gems? -%>
51
+ group :development do
50
52
  # Use console on exceptions pages [https://github.com/rails/web-console]
51
53
  gem "web-console"
54
+ <%- if RUBY_VERSION < "3.2" -%>
52
55
 
53
- # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
54
- # gem "rack-mini-profiler"
55
-
56
+ # Highlight the fine-grained location where an error occurred [https://github.com/ruby/error_highlight]
57
+ gem "error_highlight", ">= 0.4.0", platforms: [ :ruby ]
56
58
  <%- end -%>
57
- # Speed up commands on slow machines / big apps [https://github.com/rails/spring]
58
- # gem "spring"
59
59
  end
60
+ <%- end -%>
60
61
 
61
62
  <%- if depends_on_system_test? -%>
62
63
  group :test do
63
64
  # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
64
65
  gem "capybara"
65
66
  gem "selenium-webdriver"
66
- <%- if RUBY_VERSION < "3.0" -%>
67
- gem "webdrivers"
68
- <% end %>
69
67
  end
70
68
  <%- end -%>
@@ -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,11 +1,18 @@
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">
6
7
  <%%= csrf_meta_tags %>
7
8
  <%%= csp_meta_tag %>
8
9
 
10
+ <%%= yield :head %>
11
+
12
+ <link rel="manifest" href="/manifest.json">
13
+ <link rel="icon" href="/icon.png" type="image/png">
14
+ <link rel="icon" href="/icon.svg" type="image/svg+xml">
15
+ <link rel="apple-touch-icon" href="/icon.png">
9
16
  <%- if options[:skip_hotwire] || options[:skip_javascript] -%>
10
17
  <%%= stylesheet_link_tag "application" %>
11
18
  <%- else -%>
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
5
  <style>
6
6
  /* Email styles need to be inline */
7
7
  </style>
@@ -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
+ }