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,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- activesupport_path = File.expand_path("../../../activesupport/lib", __dir__)
4
- $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
5
-
6
3
  require "thor/group"
7
4
  require "rails/command"
8
5
 
@@ -26,6 +23,7 @@ module Rails
26
23
  autoload :NamedBase, "rails/generators/named_base"
27
24
  autoload :ResourceHelpers, "rails/generators/resource_helpers"
28
25
  autoload :TestCase, "rails/generators/test_case"
26
+ autoload :Devcontainer, "rails/generators/devcontainer"
29
27
 
30
28
  mattr_accessor :namespace
31
29
 
@@ -33,7 +31,7 @@ module Rails
33
31
  rails: {
34
32
  actions: "-a",
35
33
  orm: "-o",
36
- javascripts: "-j",
34
+ javascripts: ["-j", "--js"],
37
35
  resource_controller: "-c",
38
36
  scaffold_controller: "-c",
39
37
  stylesheets: "-y",
@@ -93,7 +91,7 @@ module Rails
93
91
  end
94
92
 
95
93
  # Hold configured generators fallbacks. If a plugin developer wants a
96
- # generator group to fallback to another group in case of missing generators,
94
+ # generator group to fall back to another group in case of missing generators,
97
95
  # they can add a fallback.
98
96
  #
99
97
  # For example, shoulda is considered a test_framework and is an extension
@@ -166,7 +164,8 @@ module Rails
166
164
 
167
165
  # Show help message with available generators.
168
166
  def help(command = "generate")
169
- puts "Usage: rails #{command} GENERATOR [args] [options]"
167
+ puts "Usage:"
168
+ puts " bin/rails #{command} GENERATOR [args] [options]"
170
169
  puts
171
170
  puts "General options:"
172
171
  puts " -h, [--help] # Print generator's options and usage"
@@ -204,7 +203,6 @@ module Rails
204
203
  rails.map! { |n| n.delete_prefix("rails:") }
205
204
  rails.delete("app")
206
205
  rails.delete("plugin")
207
- rails.delete("encrypted_secrets")
208
206
  rails.delete("encrypted_file")
209
207
  rails.delete("encryption_key_file")
210
208
  rails.delete("master_key")
@@ -264,16 +262,10 @@ module Rails
264
262
  run_after_generate_callback if config[:behavior] == :invoke
265
263
  else
266
264
  options = sorted_groups.flat_map(&:last)
267
- error = Command::Base::CorrectableError.new("Could not find generator '#{namespace}'.", namespace, options)
268
-
269
- if error.respond_to?(:detailed_message)
270
- formatted_message = error.detailed_message
271
- else
272
- formatted_message = error.message
273
- end
265
+ error = Command::CorrectableNameError.new("Could not find generator '#{namespace}'.", namespace, options)
274
266
 
275
267
  puts <<~MSG
276
- #{formatted_message}
268
+ #{error.detailed_message}
277
269
  Run `bin/rails generate --help` for more options.
278
270
  MSG
279
271
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ # Built-in Health Check Endpoint
5
+ #
6
+ # \Rails also comes with a built-in health check endpoint that is reachable at
7
+ # the +/up+ path. This endpoint will return a 200 status code if the app has
8
+ # booted with no exceptions, and a 500 status code otherwise.
9
+ #
10
+ # In production, many applications are required to report their status upstream,
11
+ # whether it's to an uptime monitor that will page an engineer when things go
12
+ # wrong, or a load balancer or Kubernetes controller used to determine a pod's
13
+ # health. This health check is designed to be a one-size fits all that will work
14
+ # in many situations.
15
+ #
16
+ # While any newly generated \Rails applications will have the health check at
17
+ # +/up+, you can configure the path to be anything you'd like in your
18
+ # <tt>"config/routes.rb"</tt>:
19
+ #
20
+ # Rails.application.routes.draw do
21
+ # get "healthz" => "rails/health#show", as: :rails_health_check
22
+ # end
23
+ #
24
+ # The health check will now be accessible via the +/healthz+ path.
25
+ #
26
+ # NOTE: This endpoint does not reflect the status of all of your application's
27
+ # dependencies, such as the database or Redis cluster. Replace
28
+ # <tt>"rails/health#show"</tt> with your own controller action if you have
29
+ # application specific needs.
30
+ #
31
+ # Think carefully about what you want to check as it can lead to situations
32
+ # where your application is being restarted due to a third-party service going
33
+ # bad. Ideally, you should design your application to handle those outages
34
+ # gracefully.
35
+ class HealthController < ActionController::Base
36
+ rescue_from(Exception) { render_down }
37
+
38
+ def show
39
+ render_up
40
+ end
41
+
42
+ private
43
+ def render_up
44
+ render html: html_status(color: "green")
45
+ end
46
+
47
+ def render_down
48
+ render html: html_status(color: "red"), status: 500
49
+ end
50
+
51
+ def html_status(color:)
52
+ %(<!DOCTYPE html><html><body style="background-color: #{color}"></body></html>).html_safe
53
+ end
54
+ end
55
+ end
data/lib/rails/info.rb CHANGED
@@ -4,7 +4,7 @@ require "cgi"
4
4
 
5
5
  module Rails
6
6
  # This module helps build the runtime properties that are displayed in
7
- # Rails::InfoController responses. These include the active Rails version,
7
+ # Rails::InfoController responses. These include the active \Rails version,
8
8
  # Ruby version, Rack version, and so on.
9
9
  module Info
10
10
  mattr_accessor :properties, default: []
@@ -95,11 +95,11 @@ module Rails
95
95
 
96
96
  # The name of the database adapter for the current environment.
97
97
  property "Database adapter" do
98
- ActiveRecord::Base.connection.pool.db_config.adapter
98
+ ActiveRecord::Base.connection_pool.db_config.adapter
99
99
  end
100
100
 
101
101
  property "Database schema version" do
102
- ActiveRecord::Base.connection.migration_context.current_version rescue nil
102
+ ActiveRecord::Base.connection_pool.migration_context.current_version rescue nil
103
103
  end
104
104
  end
105
105
  end
@@ -4,7 +4,7 @@ require "rails/application_controller"
4
4
  require "action_dispatch/routing/inspector"
5
5
 
6
6
  class Rails::InfoController < Rails::ApplicationController # :nodoc:
7
- prepend_view_path ActionDispatch::DebugView::RESCUES_TEMPLATE_PATH
7
+ prepend_view_path ActionDispatch::DebugView::RESCUES_TEMPLATE_PATHS
8
8
  layout -> { request.xhr? ? false : "application" }
9
9
 
10
10
  before_action :require_local!
@@ -19,12 +19,12 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
19
19
  end
20
20
 
21
21
  def routes
22
- if path = params[:path]
23
- path = URI::DEFAULT_PARSER.escape path
24
- normalized_path = with_leading_slash path
22
+ if query = params[:query]
23
+ query = URI::DEFAULT_PARSER.escape query
24
+
25
25
  render json: {
26
- exact: match_route { |it| it.match normalized_path },
27
- fuzzy: match_route { |it| it.spec.to_s.match path }
26
+ exact: matching_routes(query: query, exact_match: true),
27
+ fuzzy: matching_routes(query: query, exact_match: false)
28
28
  }
29
29
  else
30
30
  @routes_inspector = ActionDispatch::Routing::RoutesInspector.new(_routes.routes)
@@ -33,11 +33,31 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
33
33
  end
34
34
 
35
35
  private
36
- def match_route
37
- _routes.routes.filter_map { |route| route.path.spec.to_s if yield route.path }
38
- end
36
+ def matching_routes(query:, exact_match:)
37
+ return [] if query.blank?
38
+
39
+ normalized_path = ("/" + query).squeeze("/")
40
+ query_without_url_or_path_suffix = query.gsub(/(\w)(_path$)/, '\1').gsub(/(\w)(_url$)/, '\1')
41
+
42
+ _routes.routes.filter_map do |route|
43
+ route_wrapper = ActionDispatch::Routing::RouteWrapper.new(route)
44
+
45
+ if exact_match
46
+ match = route.path.match(normalized_path)
47
+ match ||= (query_without_url_or_path_suffix === route_wrapper.name)
48
+ else
49
+ match = route_wrapper.path.match(query)
50
+ match ||= route_wrapper.name.include?(query_without_url_or_path_suffix)
51
+ end
52
+
53
+ match ||= (query === route_wrapper.verb)
54
+
55
+ unless match
56
+ controller_action = URI::DEFAULT_PARSER.escape(route_wrapper.reqs)
57
+ match = exact_match ? (query === controller_action) : controller_action.include?(query)
58
+ end
39
59
 
40
- def with_leading_slash(path)
41
- ("/" + path).squeeze("/")
60
+ route_wrapper.path if match
61
+ end
42
62
  end
43
63
  end
@@ -1,26 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails/application_controller"
4
+ require "active_support/core_ext/enumerable"
4
5
 
5
6
  class Rails::MailersController < Rails::ApplicationController # :nodoc:
6
- prepend_view_path ActionDispatch::DebugView::RESCUES_TEMPLATE_PATH
7
+ prepend_view_path ActionDispatch::DebugView::RESCUES_TEMPLATE_PATHS
7
8
 
8
- around_action :set_locale, only: :preview
9
- before_action :find_preview, only: :preview
9
+ around_action :set_locale, only: [:preview, :download]
10
+ before_action :find_preview, only: [:preview, :download]
10
11
  before_action :require_local!, unless: :show_previews?
11
12
 
12
- helper_method :part_query, :locale_query
13
+ helper_method :attachment_url, :part_query, :locale_query
13
14
 
14
15
  content_security_policy(false)
15
16
 
16
17
  def index
17
18
  @previews = ActionMailer::Preview.all
18
- @page_title = "Mailer Previews"
19
+ @page_title = "Action Mailer Previews"
20
+ end
21
+
22
+ def download
23
+ @email_action = File.basename(params[:path])
24
+ if @preview.email_exists?(@email_action)
25
+ @email = @preview.call(@email_action, params)
26
+ send_data @email.to_s, filename: "#{@email_action}.eml"
27
+ else
28
+ raise AbstractController::ActionNotFound, "Email '#{@email_action}' not found in #{@preview.name}"
29
+ end
19
30
  end
20
31
 
21
32
  def preview
22
33
  if params[:path] == @preview.preview_name
23
- @page_title = "Mailer Previews for #{@preview.preview_name}"
34
+ @page_title = "Action Mailer Previews for #{@preview.preview_name}"
24
35
  render action: "mailer"
25
36
  else
26
37
  @email_action = File.basename(params[:path])
@@ -28,6 +39,8 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
28
39
  if @preview.email_exists?(@email_action)
29
40
  @page_title = "Mailer Preview for #{@preview.preview_name}##{@email_action}"
30
41
  @email = @preview.call(@email_action, params)
42
+ @attachments = attachments_for(@email).reject { |filename, attachment| attachment.inline? }
43
+ @inline_attachments = attachments_for(@email).select { |filename, attachment| attachment.inline? }
31
44
 
32
45
  if params[:part]
33
46
  part_type = Mime::Type.lookup(params[:part])
@@ -85,6 +98,16 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
85
98
  end
86
99
  end
87
100
 
101
+ def attachments_for(email)
102
+ email.all_parts.to_a.select(&:attachment?).index_by do |attachment|
103
+ attachment.respond_to?(:original_filename) ? attachment.original_filename : attachment.filename
104
+ end
105
+ end
106
+
107
+ def attachment_url(attachment)
108
+ "data:application/octet-stream;charset=utf-8;base64,#{Base64.encode64(attachment.body.to_s)}"
109
+ end
110
+
88
111
  def part_query(mime_type)
89
112
  request.query_parameters.merge(part: mime_type).to_query
90
113
  end
data/lib/rails/paths.rb CHANGED
@@ -4,9 +4,9 @@ require "pathname"
4
4
 
5
5
  module Rails
6
6
  module Paths
7
- # This object is an extended hash that behaves as root of the <tt>Rails::Paths</tt> system.
7
+ # This object is an extended hash that behaves as root of the Rails::Paths system.
8
8
  # It allows you to collect information about how you want to structure your application
9
- # paths through a Hash-like API. It requires you to give a physical path on initialization.
9
+ # paths through a Hash-like \API. It requires you to give a physical path on initialization.
10
10
  #
11
11
  # root = Root.new "/rails"
12
12
  # root.add "app/controllers", eager_load: true
@@ -18,7 +18,8 @@ module Rails
18
18
  # path.eager_load? # => true
19
19
  # path.is_a?(Rails::Paths::Path) # => true
20
20
  #
21
- # The +Path+ object is simply an enumerable and allows you to easily add extra paths:
21
+ # The Path[rdoc-ref:Rails::Paths::Path] object is simply an enumerable and
22
+ # allows you to easily add extra paths:
22
23
  #
23
24
  # path.is_a?(Enumerable) # => true
24
25
  # path.to_ary.inspect # => ["app/controllers"]
@@ -26,17 +27,19 @@ module Rails
26
27
  # path << "lib/controllers"
27
28
  # path.to_ary.inspect # => ["app/controllers", "lib/controllers"]
28
29
  #
29
- # Notice that when you add a path using +add+, the path object created already
30
- # contains the path with the same path value given to +add+. In some situations,
31
- # you may not want this behavior, so you can give <tt>:with</tt> as option.
30
+ # Notice that when you add a path using #add, the
31
+ # Path[rdoc-ref:Rails::Paths::Path] object created already contains the path
32
+ # with the same path value given to #add. In some situations, you may not
33
+ # want this behavior, so you can give <tt>:with</tt> as option.
32
34
  #
33
35
  # root.add "config/routes", with: "config/routes.rb"
34
36
  # root["config/routes"].inspect # => ["config/routes.rb"]
35
37
  #
36
- # The +add+ method accepts the following options as arguments:
37
- # eager_load, autoload, autoload_once, and glob.
38
+ # The #add method accepts the following options as arguments:
39
+ # +eager_load+, +autoload+, +autoload_once+, and +glob+.
38
40
  #
39
- # Finally, the +Path+ object also provides a few helpers:
41
+ # Finally, the Path[rdoc-ref:Rails::Paths::Path] object also provides a few
42
+ # helpers:
40
43
  #
41
44
  # root = Root.new "/rails"
42
45
  # root.add "app/controllers"
@@ -44,7 +47,7 @@ module Rails
44
47
  # root["app/controllers"].expanded # => ["/rails/app/controllers"]
45
48
  # root["app/controllers"].existent # => ["/rails/app/controllers"]
46
49
  #
47
- # Check the <tt>Rails::Paths::Path</tt> documentation for more information.
50
+ # Check the Rails::Paths::Path documentation for more information.
48
51
  class Root
49
52
  attr_accessor :path
50
53
 
@@ -102,8 +105,8 @@ module Rails
102
105
  private
103
106
  def filter_by(&block)
104
107
  all_paths.find_all(&block).flat_map { |path|
105
- paths = path.existent
106
- paths - path.children.flat_map { |p| yield(p) ? [] : p.existent }
108
+ paths = path.existent_directories
109
+ paths - path.children.flat_map { |p| yield(p) ? [] : p.existent_directories }
107
110
  }.uniq
108
111
  end
109
112
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/application_controller"
4
+
5
+ class Rails::PwaController < Rails::ApplicationController # :nodoc:
6
+ skip_forgery_protection
7
+
8
+ def service_worker
9
+ render template: "pwa/service-worker", layout: false
10
+ end
11
+
12
+ def manifest
13
+ render template: "pwa/manifest", layout: false
14
+ end
15
+ end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/time/conversions"
4
- require "active_support/core_ext/object/blank"
5
4
  require "active_support/log_subscriber"
6
5
  require "rack/body_proxy"
7
6
 
@@ -21,39 +20,45 @@ module Rails
21
20
  def call(env)
22
21
  request = ActionDispatch::Request.new(env)
23
22
 
24
- if logger.respond_to?(:tagged)
25
- logger.tagged(compute_tags(request)) { call_app(request, env) }
23
+ env["rails.rack_logger_tag_count"] = if logger.respond_to?(:push_tags)
24
+ logger.push_tags(*compute_tags(request)).size
26
25
  else
27
- call_app(request, env)
26
+ 0
28
27
  end
28
+
29
+ call_app(request, env)
29
30
  end
30
31
 
31
32
  private
32
33
  def call_app(request, env) # :doc:
34
+ logger_tag_pop_count = env["rails.rack_logger_tag_count"]
35
+
33
36
  instrumenter = ActiveSupport::Notifications.instrumenter
34
- instrumenter_state = instrumenter.start "request.action_dispatch", request: request
35
- instrumenter_finish = -> () {
36
- instrumenter.finish_with_state(instrumenter_state, "request.action_dispatch", request: request)
37
- }
37
+ handle = instrumenter.build_handle("request.action_dispatch", { request: request })
38
+ handle.start
38
39
 
39
40
  logger.info { started_request_message(request) }
40
- status, headers, body = @app.call(env)
41
- body = ::Rack::BodyProxy.new(body, &instrumenter_finish)
42
- [status, headers, body]
41
+ status, headers, body = response = @app.call(env)
42
+ body = ::Rack::BodyProxy.new(body) { finish_request_instrumentation(handle, logger_tag_pop_count) }
43
+
44
+ if response.frozen?
45
+ [status, headers, body]
46
+ else
47
+ response[2] = body
48
+ response
49
+ end
43
50
  rescue Exception
44
- instrumenter_finish.call
51
+ finish_request_instrumentation(handle, logger_tag_pop_count)
45
52
  raise
46
- ensure
47
- ActiveSupport::LogSubscriber.flush_all!
48
53
  end
49
54
 
50
55
  # Started GET "/session/new" for 127.0.0.1 at 2012-09-26 14:51:42 -0700
51
56
  def started_request_message(request) # :doc:
52
- 'Started %s "%s" for %s at %s' % [
57
+ sprintf('Started %s "%s" for %s at %s',
53
58
  request.raw_request_method,
54
59
  request.filtered_path,
55
60
  request.remote_ip,
56
- Time.now.to_default_s ]
61
+ Time.now)
57
62
  end
58
63
 
59
64
  def compute_tags(request) # :doc:
@@ -72,6 +77,12 @@ module Rails
72
77
  def logger
73
78
  Rails.logger
74
79
  end
80
+
81
+ def finish_request_instrumentation(handle, logger_tag_pop_count)
82
+ handle.finish
83
+ logger.pop_tags(logger_tag_pop_count) if logger.respond_to?(:pop_tags) && logger_tag_pop_count > 0
84
+ ActiveSupport::LogSubscriber.flush_all!
85
+ end
75
86
  end
76
87
  end
77
88
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :enddoc:
4
+
5
+ module Rails
6
+ module Rackup
7
+ begin
8
+ require "rackup/server"
9
+ Server = ::Rackup::Server
10
+ rescue LoadError
11
+ require "rack/server"
12
+ Server = ::Rack::Server
13
+ end
14
+ end
15
+ end
@@ -27,8 +27,8 @@ module Rails
27
27
  end
28
28
 
29
29
  private
30
- def method_missing(*args, &block)
31
- instance.send(*args, &block)
30
+ def method_missing(...)
31
+ instance.send(...)
32
32
  end
33
33
  end
34
34
  end
@@ -71,6 +71,11 @@ module Rails
71
71
  ActiveSupport.on_load(:after_initialize, yield: true, &block)
72
72
  end
73
73
 
74
+ # Called after application routes have been loaded.
75
+ def after_routes_loaded(&block)
76
+ ActiveSupport.on_load(:after_routes_loaded, yield: true, &block)
77
+ end
78
+
74
79
  # Array of callbacks defined by #to_prepare.
75
80
  def to_prepare_blocks
76
81
  @@to_prepare_blocks ||= []
@@ -87,9 +92,17 @@ module Rails
87
92
  end
88
93
 
89
94
  private
95
+ def actual_method?(key)
96
+ !@@options.key?(key) && respond_to?(key)
97
+ end
98
+
90
99
  def method_missing(name, *args, &blk)
91
100
  if name.end_with?("=")
92
- @@options[:"#{name[0..-2]}"] = args.first
101
+ key = name[0..-2].to_sym
102
+ if actual_method?(key)
103
+ raise NoMethodError.new("Cannot assign to `#{key}`, it is a configuration method")
104
+ end
105
+ @@options[key] = args.first
93
106
  elsif @@options.key?(name)
94
107
  @@options[name]
95
108
  else
data/lib/rails/railtie.rb CHANGED
@@ -7,34 +7,34 @@ require "active_support/core_ext/module/introspection"
7
7
  require "active_support/core_ext/module/delegation"
8
8
 
9
9
  module Rails
10
- # <tt>Rails::Railtie</tt> is the core of the Rails framework and provides
11
- # several hooks to extend Rails and/or modify the initialization process.
10
+ # +Rails::Railtie+ is the core of the \Rails framework and provides
11
+ # several hooks to extend \Rails and/or modify the initialization process.
12
12
  #
13
- # Every major component of Rails (Action Mailer, Action Controller, Active
13
+ # Every major component of \Rails (Action Mailer, Action Controller, Active
14
14
  # Record, etc.) implements a railtie. Each of them is responsible for their
15
- # own initialization. This makes Rails itself absent of any component hooks,
16
- # allowing other components to be used in place of any of the Rails defaults.
15
+ # own initialization. This makes \Rails itself absent of any component hooks,
16
+ # allowing other components to be used in place of any of the \Rails defaults.
17
17
  #
18
- # Developing a Rails extension does _not_ require implementing a railtie, but
19
- # if you need to interact with the Rails framework during or after boot, then
18
+ # Developing a \Rails extension does _not_ require implementing a railtie, but
19
+ # if you need to interact with the \Rails framework during or after boot, then
20
20
  # a railtie is needed.
21
21
  #
22
22
  # For example, an extension doing any of the following would need a railtie:
23
23
  #
24
24
  # * creating initializers
25
- # * configuring a Rails framework for the application, like setting a generator
25
+ # * configuring a \Rails framework for the application, like setting a generator
26
26
  # * adding <tt>config.*</tt> keys to the environment
27
27
  # * setting up a subscriber with ActiveSupport::Notifications
28
28
  # * adding Rake tasks
29
29
  #
30
30
  # == Creating a Railtie
31
31
  #
32
- # To extend Rails using a railtie, create a subclass of <tt>Rails::Railtie</tt>.
33
- # This class must be loaded during the Rails boot process, and is conventionally
34
- # called <tt>MyNamespace::Railtie</tt>.
32
+ # To extend \Rails using a railtie, create a subclass of +Rails::Railtie+.
33
+ # This class must be loaded during the \Rails boot process, and is conventionally
34
+ # called +MyNamespace::Railtie+.
35
35
  #
36
36
  # The following example demonstrates an extension which can be used with or
37
- # without Rails.
37
+ # without \Rails.
38
38
  #
39
39
  # # lib/my_gem/railtie.rb
40
40
  # module MyGem
@@ -47,7 +47,7 @@ module Rails
47
47
  #
48
48
  # == Initializers
49
49
  #
50
- # To add an initialization step to the Rails boot process from your railtie, just
50
+ # To add an initialization step to the \Rails boot process from your railtie, just
51
51
  # define the initialization code with the +initializer+ macro:
52
52
  #
53
53
  # class MyRailtie < Rails::Railtie
@@ -87,7 +87,7 @@ module Rails
87
87
  #
88
88
  # == Loading Rake Tasks and Generators
89
89
  #
90
- # If your railtie has Rake tasks, you can tell Rails to load them through the method
90
+ # If your railtie has Rake tasks, you can tell \Rails to load them through the method
91
91
  # +rake_tasks+:
92
92
  #
93
93
  # class MyRailtie < Rails::Railtie
@@ -96,7 +96,7 @@ module Rails
96
96
  # end
97
97
  # end
98
98
  #
99
- # By default, Rails loads generators from your load path. However, if you want to place
99
+ # By default, \Rails loads generators from your load path. However, if you want to place
100
100
  # your generators at a different location, you can specify in your railtie a block which
101
101
  # will load them during normal generators lookup:
102
102
  #
@@ -109,13 +109,13 @@ module Rails
109
109
  # Since filenames on the load path are shared across gems, be sure that files you load
110
110
  # through a railtie have unique names.
111
111
  #
112
- # == Run another program when the Rails server starts
112
+ # == Run another program when the \Rails server starts
113
113
  #
114
- # In development, it's very usual to have to run another process next to the Rails Server. In example
114
+ # In development, it's very usual to have to run another process next to the \Rails Server. In example
115
115
  # you might want to start the Webpack or React server. Or maybe you need to run your job scheduler process
116
116
  # like Sidekiq. This is usually done by opening a new shell and running the program from here.
117
117
  #
118
- # Rails allow you to specify a +server+ block which will get called when a Rails server starts.
118
+ # \Rails allow you to specify a +server+ block which will get called when a \Rails server starts.
119
119
  # This way, your users don't need to remember to have to open a new shell and run another program, making
120
120
  # this less confusing for everyone.
121
121
  # It can be used like this:
@@ -221,14 +221,13 @@ module Rails
221
221
 
222
222
  # If the class method does not have a method, then send the method call
223
223
  # to the Railtie instance.
224
- def method_missing(name, *args, &block)
224
+ def method_missing(name, ...)
225
225
  if !abstract_railtie? && instance.respond_to?(name)
226
- instance.public_send(name, *args, &block)
226
+ instance.public_send(name, ...)
227
227
  else
228
228
  super
229
229
  end
230
230
  end
231
- ruby2_keywords(:method_missing)
232
231
 
233
232
  # receives an instance variable identifier, set the variable value if is
234
233
  # blank and append given block to value, which will be used later in