railties 7.0.8 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +188 -268
  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 +110 -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 +93 -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 +137 -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 +51 -23
  66. data/lib/rails/gem_version.rb +3 -3
  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 +132 -82
  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 +37 -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 +2 -0
  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 +24 -34
  108. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +9 -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 +43 -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 +4 -4
  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 +7 -15
  167. data/lib/rails/health_controller.rb +55 -0
  168. data/lib/rails/info.rb +3 -3
  169. data/lib/rails/info_controller.rb +31 -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 +20 -21
  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 +89 -42
  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,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
3
4
  require "active_support/core_ext/string/inflections"
4
5
  require "active_support/core_ext/array/conversions"
5
6
  require "active_support/descendants_tracker"
@@ -11,22 +12,27 @@ module Rails
11
12
  include Initializable
12
13
 
13
14
  initializer :add_generator_templates do
14
- config.generators.templates.unshift(*paths["lib/templates"].existent)
15
+ ensure_generator_templates_added
15
16
  end
16
17
 
17
18
  initializer :setup_main_autoloader do
18
19
  autoloader = Rails.autoloaders.main
19
20
 
21
+ # Normally empty, but if the user already defined some, we won't
22
+ # override them. Important if there are custom namespaces associated.
23
+ already_configured_dirs = Set.new(autoloader.dirs)
24
+
20
25
  ActiveSupport::Dependencies.autoload_paths.freeze
21
26
  ActiveSupport::Dependencies.autoload_paths.uniq.each do |path|
22
27
  # Zeitwerk only accepts existing directories in `push_dir`.
23
28
  next unless File.directory?(path)
29
+ next if already_configured_dirs.member?(path.to_s)
24
30
 
25
31
  autoloader.push_dir(path)
26
32
  autoloader.do_not_eager_load(path) unless ActiveSupport::Dependencies.eager_load?(path)
27
33
  end
28
34
 
29
- unless config.cache_classes
35
+ if config.reloading_enabled?
30
36
  autoloader.enable_reloading
31
37
  ActiveSupport::Dependencies.autoloader = autoloader
32
38
 
@@ -72,9 +78,10 @@ module Rails
72
78
  if config.eager_load
73
79
  ActiveSupport.run_load_hooks(:before_eager_load, self)
74
80
  Zeitwerk::Loader.eager_load_all
81
+ Rails.eager_load!
75
82
  config.eager_load_namespaces.each(&:eager_load!)
76
83
 
77
- unless config.cache_classes
84
+ if config.reloading_enabled?
78
85
  app.reloader.after_class_unload do
79
86
  Rails.autoloaders.main.eager_load
80
87
  end
@@ -125,10 +132,7 @@ module Rails
125
132
  else
126
133
  # Default concurrency setting: enabled, but safe
127
134
 
128
- unless config.cache_classes && config.eager_load
129
- # Without cache_classes + eager_load, the load interlock
130
- # is required for proper operation
131
-
135
+ if config.reloading_enabled?
132
136
  app.executor.register_hook(InterlockHook, outer: true)
133
137
  end
134
138
  end
@@ -157,6 +161,7 @@ module Rails
157
161
  reloader.eager_load = app.config.eager_load
158
162
  reloader.execute
159
163
  reloaders << reloader
164
+
160
165
  app.reloader.to_run do
161
166
  # We configure #execute rather than #execute_if_updated because if
162
167
  # autoloaded constants are cleared we need to reload routes also in
@@ -169,7 +174,10 @@ module Rails
169
174
  # some sort of reloaders dependency support, to be added.
170
175
  require_unload_lock!
171
176
  reloader.execute
177
+ ActiveSupport.run_load_hooks(:after_routes_loaded, self)
172
178
  end
179
+
180
+ ActiveSupport.run_load_hooks(:after_routes_loaded, self)
173
181
  end
174
182
 
175
183
  # Set clearing dependencies after the finisher hook to ensure paths
@@ -181,39 +189,48 @@ module Rails
181
189
  ActiveSupport::Dependencies.clear
182
190
  end
183
191
 
184
- if config.cache_classes
185
- app.reloader.check = lambda { false }
186
- elsif config.reload_classes_only_on_change
187
- app.reloader.check = lambda do
188
- app.reloaders.map(&:updated?).any?
192
+ if config.reloading_enabled?
193
+ if config.reload_classes_only_on_change
194
+ app.reloader.check = lambda do
195
+ app.reloaders.map(&:updated?).any?
196
+ end
197
+ else
198
+ app.reloader.check = lambda { true }
189
199
  end
190
200
  else
191
- app.reloader.check = lambda { true }
201
+ app.reloader.check = lambda { false }
192
202
  end
193
203
 
194
- if config.cache_classes
195
- # No reloader
196
- ActiveSupport::DescendantsTracker.disable_clear!
197
- elsif config.reload_classes_only_on_change
198
- reloader = config.file_watcher.new(*watchable_args, &callback)
199
- reloaders << reloader
200
-
201
- # Prepend this callback to have autoloaded constants cleared before
202
- # any other possible reloading, in case they need to autoload fresh
203
- # constants.
204
- app.reloader.to_run(prepend: true) do
205
- # In addition to changes detected by the file watcher, if routes
206
- # or i18n have been updated we also need to clear constants,
207
- # that's why we run #execute rather than #execute_if_updated, this
208
- # callback has to clear autoloaded constants after any update.
209
- class_unload! do
210
- reloader.execute
204
+ if config.reloading_enabled?
205
+ if config.reload_classes_only_on_change
206
+ reloader = config.file_watcher.new(*watchable_args, &callback)
207
+ reloaders << reloader
208
+
209
+ # Prepend this callback to have autoloaded constants cleared before
210
+ # any other possible reloading, in case they need to autoload fresh
211
+ # constants.
212
+ app.reloader.to_run(prepend: true) do
213
+ # In addition to changes detected by the file watcher, if routes
214
+ # or i18n have been updated we also need to clear constants,
215
+ # that's why we run #execute rather than #execute_if_updated, this
216
+ # callback has to clear autoloaded constants after any update.
217
+ class_unload! do
218
+ reloader.execute
219
+ end
220
+ end
221
+ else
222
+ app.reloader.to_complete do
223
+ class_unload!(&callback)
211
224
  end
212
225
  end
213
226
  else
214
- app.reloader.to_complete do
215
- class_unload!(&callback)
216
- end
227
+ ActiveSupport::DescendantsTracker.disable_clear!
228
+ end
229
+ end
230
+
231
+ initializer :enable_yjit do
232
+ if config.yjit && defined?(RubyVM::YJIT.enable)
233
+ RubyVM::YJIT.enable
217
234
  end
218
235
  end
219
236
  end
@@ -4,12 +4,12 @@ require "yaml"
4
4
  require "active_support/core_ext/hash/keys"
5
5
  require "active_support/core_ext/object/blank"
6
6
  require "active_support/key_generator"
7
- require "active_support/message_verifier"
7
+ require "active_support/message_verifiers"
8
+ require "active_support/deprecation"
8
9
  require "active_support/encrypted_configuration"
9
10
  require "active_support/hash_with_indifferent_access"
10
11
  require "active_support/configuration_file"
11
12
  require "rails/engine"
12
- require "rails/secrets"
13
13
  require "rails/autoloaders"
14
14
 
15
15
  module Rails
@@ -26,7 +26,7 @@ module Rails
26
26
  #
27
27
  # Besides providing the same configuration as Rails::Engine and Rails::Railtie,
28
28
  # the application object has several specific configurations, for example
29
- # +cache_classes+, +consider_all_requests_local+, +filter_parameters+,
29
+ # +enable_reloading+, +consider_all_requests_local+, +filter_parameters+,
30
30
  # +logger+, and so forth.
31
31
  #
32
32
  # Check Rails::Application::Configuration to see them all.
@@ -70,6 +70,8 @@ module Rails
70
70
  def inherited(base)
71
71
  super
72
72
  Rails.app_class = base
73
+ # lib has to be added to $LOAD_PATH unconditionally, even if it's in the
74
+ # autoload paths and config.add_autoload_paths_to_load_path is false.
73
75
  add_lib_to_load_path!(find_root(base.called_from))
74
76
  ActiveSupport.run_load_hooks(:before_configuration, base)
75
77
  end
@@ -101,7 +103,7 @@ module Rails
101
103
  delegate :default_url_options, :default_url_options=, to: :routes
102
104
 
103
105
  INITIAL_VARIABLES = [:config, :railties, :routes_reloader, :reloaders,
104
- :routes, :helpers, :app_env_config, :secrets] # :nodoc:
106
+ :routes, :helpers, :app_env_config] # :nodoc:
105
107
 
106
108
  def initialize(initial_variable_values = {}, &block)
107
109
  super()
@@ -111,7 +113,9 @@ module Rails
111
113
  @app_env_config = nil
112
114
  @ordered_railties = nil
113
115
  @railties = nil
114
- @message_verifiers = {}
116
+ @key_generators = {}
117
+ @message_verifiers = nil
118
+ @deprecators = nil
115
119
  @ran_load_hooks = false
116
120
 
117
121
  @executor = Class.new(ActiveSupport::Executor)
@@ -149,15 +153,53 @@ module Rails
149
153
  routes_reloader.reload!
150
154
  end
151
155
 
152
- # Returns the application's KeyGenerator
153
- def key_generator
156
+ # Returns a key generator (ActiveSupport::CachingKeyGenerator) for a
157
+ # specified +secret_key_base+. The return value is memoized, so additional
158
+ # calls with the same +secret_key_base+ will return the same key generator
159
+ # instance.
160
+ def key_generator(secret_key_base = self.secret_key_base)
154
161
  # number of iterations selected based on consultation with the google security
155
162
  # team. Details at https://github.com/rails/rails/pull/6952#issuecomment-7661220
156
- @caching_key_generator ||= ActiveSupport::CachingKeyGenerator.new(
163
+ @key_generators[secret_key_base] ||= ActiveSupport::CachingKeyGenerator.new(
157
164
  ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
158
165
  )
159
166
  end
160
167
 
168
+ # Returns a message verifier factory (ActiveSupport::MessageVerifiers). This
169
+ # factory can be used as a central point to configure and create message
170
+ # verifiers (ActiveSupport::MessageVerifier) for your application.
171
+ #
172
+ # By default, message verifiers created by this factory will generate
173
+ # messages using the default ActiveSupport::MessageVerifier options. You can
174
+ # override these options with a combination of
175
+ # ActiveSupport::MessageVerifiers#clear_rotations and
176
+ # ActiveSupport::MessageVerifiers#rotate. However, this must be done prior
177
+ # to building any message verifier instances. For example, in a
178
+ # +before_initialize+ block:
179
+ #
180
+ # # Use `url_safe: true` when generating messages
181
+ # config.before_initialize do |app|
182
+ # app.message_verifiers.clear_rotations
183
+ # app.message_verifiers.rotate(url_safe: true)
184
+ # end
185
+ #
186
+ # Message verifiers created by this factory will always use a secret derived
187
+ # from #secret_key_base when generating messages. +clear_rotations+ will not
188
+ # affect this behavior. However, older +secret_key_base+ values can be
189
+ # rotated for verifying messages:
190
+ #
191
+ # # Fall back to old `secret_key_base` when verifying messages
192
+ # config.before_initialize do |app|
193
+ # app.message_verifiers.rotate(secret_key_base: "old secret_key_base")
194
+ # end
195
+ #
196
+ def message_verifiers
197
+ @message_verifiers ||=
198
+ ActiveSupport::MessageVerifiers.new do |salt, secret_key_base: self.secret_key_base|
199
+ key_generator(secret_key_base).generate_key(salt)
200
+ end.rotate_defaults
201
+ end
202
+
161
203
  # Returns a message verifier object.
162
204
  #
163
205
  # This verifier can be used to generate and verify signed messages in the application.
@@ -165,27 +207,36 @@ module Rails
165
207
  # It is recommended not to use the same verifier for different things, so you can get different
166
208
  # verifiers passing the +verifier_name+ argument.
167
209
  #
210
+ # For instance, +ActiveStorage::Blob.signed_id_verifier+ is implemented using this feature, which assures that
211
+ # the IDs strings haven't been tampered with and are safe to use in a finder.
212
+ #
213
+ # See the ActiveSupport::MessageVerifier documentation for more information.
214
+ #
168
215
  # ==== Parameters
169
216
  #
170
217
  # * +verifier_name+ - the name of the message verifier.
171
218
  #
172
219
  # ==== Examples
173
220
  #
174
- # message = Rails.application.message_verifier('sensitive_data').generate('my sensible data')
175
- # Rails.application.message_verifier('sensitive_data').verify(message)
176
- # # => 'my sensible data'
177
- #
178
- # See the ActiveSupport::MessageVerifier documentation for more information.
221
+ # message = Rails.application.message_verifier('my_purpose').generate('data to sign against tampering')
222
+ # Rails.application.message_verifier('my_purpose').verify(message)
223
+ # # => 'data to sign against tampering'
179
224
  def message_verifier(verifier_name)
180
- @message_verifiers[verifier_name] ||= begin
181
- secret = key_generator.generate_key(verifier_name.to_s)
182
- ActiveSupport::MessageVerifier.new(secret)
225
+ message_verifiers[verifier_name]
226
+ end
227
+
228
+ # A managed collection of deprecators (ActiveSupport::Deprecation::Deprecators).
229
+ # The collection's configuration methods affect all deprecators in the
230
+ # collection. Additionally, the collection's +silence+ method silences all
231
+ # deprecators in the collection for the duration of a given block.
232
+ def deprecators
233
+ @deprecators ||= ActiveSupport::Deprecation::Deprecators.new.tap do |deprecators|
234
+ deprecators[:railties] = Rails.deprecator
183
235
  end
184
236
  end
185
237
 
186
- # Convenience for loading config/foo.yml for the current Rails env.
187
- #
188
- # Examples:
238
+ # Convenience for loading config/foo.yml for the current \Rails env.
239
+ # Example:
189
240
  #
190
241
  # # config/exception_notification.yml:
191
242
  # production:
@@ -196,13 +247,15 @@ module Rails
196
247
  # url: http://localhost:3001
197
248
  # namespace: my_app_development
198
249
  #
250
+ # <code></code>
251
+ #
199
252
  # # config/environments/production.rb
200
253
  # Rails.application.configure do
201
254
  # config.middleware.use ExceptionNotifier, config_for(:exception_notification)
202
255
  # end
203
256
  #
204
- # # You can also store configurations in a shared section which will be
205
- # # merged with the environment configuration
257
+ # You can also store configurations in a shared section which will be merged
258
+ # with the environment configuration
206
259
  #
207
260
  # # config/example.yml
208
261
  # shared:
@@ -215,6 +268,8 @@ module Rails
215
268
  # bar:
216
269
  # qux: 2
217
270
  #
271
+ # <code></code>
272
+ #
218
273
  # # development environment
219
274
  # Rails.application.config_for(:example)[:foo][:bar]
220
275
  # # => { baz: 1, qux: 2 }
@@ -245,16 +300,17 @@ module Rails
245
300
  end
246
301
  end
247
302
 
248
- # Stores some of the Rails initial environment parameters which
303
+ # Stores some of the \Rails initial environment parameters which
249
304
  # will be used by middlewares and engines to configure themselves.
250
305
  def env_config
251
306
  @app_env_config ||= super.merge(
252
- "action_dispatch.parameter_filter" => config.filter_parameters,
307
+ "action_dispatch.parameter_filter" => filter_parameters,
253
308
  "action_dispatch.redirect_filter" => config.filter_redirect,
254
309
  "action_dispatch.secret_key_base" => secret_key_base,
255
310
  "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
256
311
  "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
257
312
  "action_dispatch.log_rescued_responses" => config.action_dispatch.log_rescued_responses,
313
+ "action_dispatch.debug_exception_log_level" => ActiveSupport::Logger.const_get(config.action_dispatch.debug_exception_log_level.to_s.upcase),
258
314
  "action_dispatch.logger" => Rails.logger,
259
315
  "action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner,
260
316
  "action_dispatch.key_generator" => key_generator,
@@ -337,7 +393,7 @@ module Rails
337
393
  # Rails application, you will need to add lib to $LOAD_PATH on your own in case
338
394
  # you need to load files in lib/ during the application configuration as well.
339
395
  def self.add_lib_to_load_path!(root) # :nodoc:
340
- path = File.join root, "lib"
396
+ path = File.join(root, "lib")
341
397
  if File.exist?(path) && !$LOAD_PATH.include?(path)
342
398
  $LOAD_PATH.unshift(path)
343
399
  end
@@ -358,8 +414,8 @@ module Rails
358
414
  def watchable_args # :nodoc:
359
415
  files, dirs = config.watchable_files.dup, config.watchable_dirs.dup
360
416
 
361
- ActiveSupport::Dependencies.autoload_paths.each do |path|
362
- File.file?(path) ? files << path.to_s : dirs[path.to_s] = [:rb]
417
+ Rails.autoloaders.main.dirs.each do |path|
418
+ dirs[path] = [:rb]
363
419
  end
364
420
 
365
421
  [files, dirs]
@@ -385,41 +441,26 @@ module Rails
385
441
  end
386
442
 
387
443
  attr_writer :config
388
-
389
- def secrets
390
- @secrets ||= begin
391
- secrets = ActiveSupport::OrderedOptions.new
392
- files = config.paths["config/secrets"].existent
393
- files = files.reject { |path| path.end_with?(".enc") } unless config.read_encrypted_secrets
394
- secrets.merge! Rails::Secrets.parse(files, env: Rails.env)
395
-
396
- # Fallback to config.secret_key_base if secrets.secret_key_base isn't set
397
- secrets.secret_key_base ||= config.secret_key_base
398
-
399
- secrets
400
- end
401
- end
402
-
403
- attr_writer :secrets, :credentials
444
+ attr_writer :credentials
404
445
 
405
446
  # The secret_key_base is used as the input secret to the application's key generator, which in turn
406
447
  # is used to create all ActiveSupport::MessageVerifier and ActiveSupport::MessageEncryptor instances,
407
448
  # including the ones that sign and encrypt cookies.
408
449
  #
409
450
  # In development and test, this is randomly generated and stored in a
410
- # temporary file in <tt>tmp/development_secret.txt</tt>.
451
+ # temporary file in <tt>tmp/local_secret.txt</tt>.
452
+ #
453
+ # You can also set <tt>ENV["SECRET_KEY_BASE_DUMMY"]</tt> to trigger the use of a randomly generated
454
+ # secret_key_base that's stored in a temporary file. This is useful when precompiling assets for
455
+ # production as part of a build step that otherwise does not need access to the production secrets.
456
+ #
457
+ # Dockerfile example: <tt>RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rails assets:precompile</tt>.
411
458
  #
412
459
  # In all other environments, we look for it first in <tt>ENV["SECRET_KEY_BASE"]</tt>,
413
- # then +credentials.secret_key_base+, and finally +secrets.secret_key_base+. For most applications,
414
- # the correct place to store it is in the encrypted credentials file.
460
+ # then +credentials.secret_key_base+. For most applications, the correct place to store it is in the
461
+ # encrypted credentials file.
415
462
  def secret_key_base
416
- if Rails.env.development? || Rails.env.test?
417
- secrets.secret_key_base ||= generate_development_secret
418
- else
419
- validate_secret_key_base(
420
- ENV["SECRET_KEY_BASE"] || credentials.secret_key_base || secrets.secret_key_base
421
- )
422
- end
463
+ config.secret_key_base
423
464
  end
424
465
 
425
466
  # Returns an ActiveSupport::EncryptedConfiguration instance for the
@@ -488,6 +529,11 @@ module Rails
488
529
  ordered_railties.flatten - [self]
489
530
  end
490
531
 
532
+ def load_generators(app = self) # :nodoc:
533
+ app.ensure_generator_templates_added
534
+ super
535
+ end
536
+
491
537
  # Eager loads the application code.
492
538
  def eager_load!
493
539
  Rails.autoloaders.each(&:eager_load)
@@ -567,33 +613,12 @@ module Rails
567
613
  default_stack.build_stack
568
614
  end
569
615
 
570
- def validate_secret_key_base(secret_key_base)
571
- if secret_key_base.is_a?(String) && secret_key_base.present?
572
- secret_key_base
573
- elsif secret_key_base
574
- raise ArgumentError, "`secret_key_base` for #{Rails.env} environment must be a type of String`"
575
- else
576
- raise ArgumentError, "Missing `secret_key_base` for '#{Rails.env}' environment, set this string with `bin/rails credentials:edit`"
577
- end
616
+ def ensure_generator_templates_added
617
+ configured_paths = config.generators.templates
618
+ configured_paths.unshift(*(paths["lib/templates"].existent - configured_paths))
578
619
  end
579
620
 
580
621
  private
581
- def generate_development_secret
582
- if secrets.secret_key_base.nil?
583
- key_file = Rails.root.join("tmp/development_secret.txt")
584
-
585
- if !File.exist?(key_file)
586
- random_key = SecureRandom.hex(64)
587
- FileUtils.mkdir_p(key_file.dirname)
588
- File.binwrite(key_file, random_key)
589
- end
590
-
591
- secrets.secret_key_base = File.binread(key_file)
592
- end
593
-
594
- secrets.secret_key_base
595
- end
596
-
597
622
  def build_request(env)
598
623
  req = super
599
624
  env["ORIGINAL_FULLPATH"] = req.fullpath
@@ -608,5 +633,14 @@ module Rails
608
633
  def coerce_same_site_protection(protection)
609
634
  protection.respond_to?(:call) ? protection : proc { protection }
610
635
  end
636
+
637
+ def filter_parameters
638
+ if config.precompile_filter_parameters
639
+ config.filter_parameters.replace(
640
+ ActiveSupport::ParameterFilter.precompile_filters(config.filter_parameters)
641
+ )
642
+ end
643
+ config.filter_parameters
644
+ end
611
645
  end
612
646
  end
@@ -4,15 +4,17 @@ require "active_support/backtrace_cleaner"
4
4
  require "active_support/core_ext/string/access"
5
5
 
6
6
  module Rails
7
- class BacktraceCleaner < ActiveSupport::BacktraceCleaner
7
+ class BacktraceCleaner < ActiveSupport::BacktraceCleaner # :nodoc:
8
8
  APP_DIRS_PATTERN = /\A(?:\.\/)?(?:app|config|lib|test|\(\w*\))/
9
- RENDER_TEMPLATE_PATTERN = /:in `.*_\w+_{2,3}\d+_\d+'/
9
+ RENDER_TEMPLATE_PATTERN = /:in [`'].*_\w+_{2,3}\d+_\d+'/
10
10
 
11
11
  def initialize
12
12
  super
13
- @root = "#{Rails.root}/"
14
13
  add_filter do |line|
15
- line.start_with?(@root) ? line.from(@root.size) : line
14
+ # We may be called before Rails.root is assigned.
15
+ # When that happens we fallback to not truncating.
16
+ @root ||= Rails.root && "#{Rails.root}/"
17
+ @root && line.start_with?(@root) ? line.from(@root.size) : line
16
18
  end
17
19
  add_filter do |line|
18
20
  if RENDER_TEMPLATE_PATTERN.match?(line)
@@ -23,5 +25,18 @@ module Rails
23
25
  end
24
26
  add_silencer { |line| !APP_DIRS_PATTERN.match?(line) }
25
27
  end
28
+
29
+ def clean(backtrace, kind = :silent)
30
+ kind = nil if ENV["BACKTRACE"]
31
+
32
+ super(backtrace, kind)
33
+ end
34
+ alias_method :filter, :clean
35
+
36
+ def clean_frame(frame, kind = :silent)
37
+ kind = nil if ENV["BACKTRACE"]
38
+
39
+ super(frame, kind)
40
+ end
26
41
  end
27
42
  end
data/lib/rails/cli.rb CHANGED
@@ -6,12 +6,14 @@ require "rails/app_loader"
6
6
  # the rest of this script is not run.
7
7
  Rails::AppLoader.exec_app
8
8
 
9
- require "rails/ruby_version_check"
10
9
  Signal.trap("INT") { puts; exit(1) }
11
10
 
12
11
  require "rails/command"
13
-
14
- if ARGV.first == "plugin"
12
+ case ARGV.first
13
+ when Rails::Command::HELP_MAPPINGS, "help", nil
14
+ ARGV.shift
15
+ Rails::Command.invoke :gem_help, ARGV
16
+ when "plugin"
15
17
  ARGV.shift
16
18
  Rails::Command.invoke :plugin, ARGV
17
19
  else
@@ -10,23 +10,21 @@ module Rails
10
10
  Dir.chdir(File.expand_path("../..", APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
11
11
  end
12
12
 
13
- def require_application_and_environment!
14
- require_application!
15
- require_environment!
16
- end
17
-
18
13
  def require_application!
19
14
  require ENGINE_PATH if defined?(ENGINE_PATH)
15
+ require APP_PATH if defined?(APP_PATH)
16
+ end
20
17
 
21
- if defined?(APP_PATH)
22
- require APP_PATH
23
- end
18
+ def boot_application!
19
+ require_application!
20
+ Rails.application.require_environment! if defined?(APP_PATH)
24
21
  end
25
22
 
26
- def require_environment!
27
- if defined?(APP_PATH)
28
- Rails.application.require_environment!
29
- end
23
+ def load_environment_config!
24
+ require_application!
25
+ # Only run initializers that are in the :all group, which includes the
26
+ # :load_environment_config initializer.
27
+ Rails.application.initialize!(:_) if defined?(APP_PATH)
30
28
  end
31
29
 
32
30
  if defined?(ENGINE_PATH)