railties 7.1.3.4 → 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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +177 -742
  3. data/lib/minitest/rails_plugin.rb +5 -2
  4. data/lib/rails/all.rb +1 -3
  5. data/lib/rails/api/task.rb +6 -4
  6. data/lib/rails/application/bootstrap.rb +5 -6
  7. data/lib/rails/application/configuration.rb +73 -38
  8. data/lib/rails/application/dummy_config.rb +2 -2
  9. data/lib/rails/application/finisher.rb +7 -0
  10. data/lib/rails/application.rb +15 -86
  11. data/lib/rails/backtrace_cleaner.rb +18 -3
  12. data/lib/rails/cli.rb +0 -1
  13. data/lib/rails/command.rb +1 -1
  14. data/lib/rails/commands/app/update_command.rb +93 -0
  15. data/lib/rails/commands/boot/boot_command.rb +14 -0
  16. data/lib/rails/commands/console/console_command.rb +2 -21
  17. data/lib/rails/commands/console/irb_console.rb +137 -0
  18. data/lib/rails/commands/credentials/credentials_command.rb +2 -2
  19. data/lib/rails/commands/dbconsole/dbconsole_command.rb +21 -30
  20. data/lib/rails/commands/devcontainer/devcontainer_command.rb +39 -0
  21. data/lib/rails/commands/rake/rake_command.rb +1 -1
  22. data/lib/rails/commands/runner/runner_command.rb +14 -3
  23. data/lib/rails/commands/server/server_command.rb +5 -3
  24. data/lib/rails/commands/test/test_command.rb +2 -0
  25. data/lib/rails/configuration.rb +10 -1
  26. data/lib/rails/console/app.rb +5 -32
  27. data/lib/rails/console/helpers.rb +5 -16
  28. data/lib/rails/console/methods.rb +23 -0
  29. data/lib/rails/engine.rb +5 -5
  30. data/lib/rails/gem_version.rb +3 -3
  31. data/lib/rails/generators/app_base.rb +70 -49
  32. data/lib/rails/generators/base.rb +5 -1
  33. data/lib/rails/generators/database.rb +227 -69
  34. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  35. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  36. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  37. data/lib/rails/generators/generated_attribute.rb +26 -1
  38. data/lib/rails/generators/migration.rb +3 -3
  39. data/lib/rails/generators/rails/app/app_generator.rb +53 -24
  40. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +22 -15
  41. data/lib/rails/generators/rails/app/templates/Gemfile.tt +16 -16
  42. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  43. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +8 -1
  44. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  45. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  46. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  47. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  48. data/lib/rails/generators/rails/app/templates/bin/setup.tt +6 -2
  49. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +1 -1
  50. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  51. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +7 -0
  52. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +8 -1
  53. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +3 -3
  54. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +14 -7
  55. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +5 -0
  56. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +8 -5
  57. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  58. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +70 -0
  59. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +24 -26
  60. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +4 -0
  61. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +5 -0
  62. data/lib/rails/generators/rails/app/templates/dockerignore.tt +13 -0
  63. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +138 -0
  64. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  65. data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -3
  66. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +66 -0
  67. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  68. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  69. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  70. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  71. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
  72. data/lib/rails/generators/rails/db/system/change/change_generator.rb +131 -20
  73. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +166 -0
  74. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  75. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  76. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  77. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  78. data/lib/rails/generators/rails/plugin/plugin_generator.rb +38 -7
  79. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  80. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +5 -1
  81. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  82. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  83. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  84. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  85. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  86. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  87. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  88. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  89. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +15 -1
  90. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  91. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  92. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  93. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  94. data/lib/rails/generators/testing/assertions.rb +20 -0
  95. data/lib/rails/generators/testing/behavior.rb +7 -6
  96. data/lib/rails/generators.rb +1 -1
  97. data/lib/rails/health_controller.rb +1 -1
  98. data/lib/rails/info.rb +2 -2
  99. data/lib/rails/mailers_controller.rb +14 -1
  100. data/lib/rails/paths.rb +2 -2
  101. data/lib/rails/pwa_controller.rb +15 -0
  102. data/lib/rails/rack/logger.rb +15 -7
  103. data/lib/rails/railtie/configurable.rb +2 -2
  104. data/lib/rails/railtie.rb +2 -3
  105. data/lib/rails/tasks/framework.rake +0 -26
  106. data/lib/rails/tasks/tmp.rake +1 -1
  107. data/lib/rails/templates/layouts/application.html.erb +1 -1
  108. data/lib/rails/templates/rails/mailers/email.html.erb +12 -8
  109. data/lib/rails/templates/rails/welcome/index.html.erb +4 -2
  110. data/lib/rails/test_help.rb +2 -4
  111. data/lib/rails/test_unit/reporter.rb +8 -2
  112. data/lib/rails/test_unit/runner.rb +26 -2
  113. data/lib/rails/test_unit/test_parser.rb +45 -0
  114. data/lib/rails.rb +7 -4
  115. metadata +42 -32
  116. data/lib/rails/app_updater.rb +0 -40
  117. data/lib/rails/commands/secrets/USAGE +0 -61
  118. data/lib/rails/commands/secrets/secrets_command.rb +0 -47
  119. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  120. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +0 -54
  121. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  122. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  123. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  124. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  125. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +0 -284
  126. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  127. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  128. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  129. data/lib/rails/ruby_version_check.rb +0 -17
  130. data/lib/rails/secrets.rb +0 -110
@@ -1,5 +1,5 @@
1
1
  require "test_helper"
2
2
 
3
3
  class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
4
- driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
4
+ driven_by :selenium, using: :headless_chrome, screen_size: [ 1400, 1400 ]
5
5
  end
@@ -121,6 +121,26 @@ module Rails
121
121
  assert_equal(value, create_generated_attribute(attribute_type).default)
122
122
  end
123
123
  end
124
+
125
+ # Asserts a given initializer exists. You need to supply a path relative
126
+ # to the `config/initializers/` directory.
127
+ #
128
+ # assert_initializer "mail_interceptors.rb"
129
+ #
130
+ # You can also give extra arguments. If the argument is a regexp, it will check if the
131
+ # regular expression matches the given file content. If it's a string, it compares the
132
+ # file with the given string:
133
+ #
134
+ # assert_initializer "mail_interceptors.rb", /SandboxEmailInterceptor/
135
+ #
136
+ # Finally, when a block is given, it yields the file content:
137
+ #
138
+ # assert_initializer "mail_interceptors.rb" do |initializer|
139
+ # assert_match(/SandboxEmailInterceptor/, initializer)
140
+ # end
141
+ def assert_initializer(name, *contents, &block)
142
+ assert_file("config/initializers/#{name}", *contents, &block)
143
+ end
124
144
  end
125
145
  end
126
146
  end
@@ -65,11 +65,15 @@ module Rails
65
65
  # You can provide a configuration hash as second argument. This method returns the output
66
66
  # printed by the generator.
67
67
  def run_generator(args = default_arguments, config = {})
68
- capture(:stdout) do
69
- args += ["--skip-bundle"] unless args.include?("--no-skip-bundle") || args.include?("--dev")
70
- args += ["--skip-bootsnap"] unless args.include?("--no-skip-bootsnap") || args.include?("--skip-bootsnap")
68
+ args += ["--skip-bundle"] unless args.include?("--no-skip-bundle") || args.include?("--dev")
69
+ args += ["--skip-bootsnap"] unless args.include?("--no-skip-bootsnap") || args.include?("--skip-bootsnap")
71
70
 
71
+ if ENV["RAILS_LOG_TO_STDOUT"] == "true"
72
72
  generator_class.start(args, config.reverse_merge(destination_root: destination_root))
73
+ else
74
+ capture(:stdout) do
75
+ generator_class.start(args, config.reverse_merge(destination_root: destination_root))
76
+ end
73
77
  end
74
78
  end
75
79
 
@@ -107,9 +111,6 @@ module Rails
107
111
  Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first
108
112
  end
109
113
  end
110
-
111
- include ActiveSupport::Deprecation::DeprecatedConstantAccessor
112
- deprecate_constant "Behaviour", "Rails::Generators::Testing::Behavior", deprecator: Rails.deprecator
113
114
  end
114
115
  end
115
116
  end
@@ -23,6 +23,7 @@ module Rails
23
23
  autoload :NamedBase, "rails/generators/named_base"
24
24
  autoload :ResourceHelpers, "rails/generators/resource_helpers"
25
25
  autoload :TestCase, "rails/generators/test_case"
26
+ autoload :Devcontainer, "rails/generators/devcontainer"
26
27
 
27
28
  mattr_accessor :namespace
28
29
 
@@ -202,7 +203,6 @@ module Rails
202
203
  rails.map! { |n| n.delete_prefix("rails:") }
203
204
  rails.delete("app")
204
205
  rails.delete("plugin")
205
- rails.delete("encrypted_secrets")
206
206
  rails.delete("encrypted_file")
207
207
  rails.delete("encryption_key_file")
208
208
  rails.delete("master_key")
@@ -24,7 +24,7 @@ module Rails
24
24
  # The health check will now be accessible via the +/healthz+ path.
25
25
  #
26
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
27
+ # dependencies, such as the database or Redis cluster. Replace
28
28
  # <tt>"rails/health#show"</tt> with your own controller action if you have
29
29
  # application specific needs.
30
30
  #
data/lib/rails/info.rb CHANGED
@@ -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
@@ -1,6 +1,7 @@
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
7
  prepend_view_path ActionDispatch::DebugView::RESCUES_TEMPLATE_PATHS
@@ -9,7 +10,7 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
9
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
 
@@ -38,6 +39,8 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
38
39
  if @preview.email_exists?(@email_action)
39
40
  @page_title = "Mailer Preview for #{@preview.preview_name}##{@email_action}"
40
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? }
41
44
 
42
45
  if params[:part]
43
46
  part_type = Mime::Type.lookup(params[:part])
@@ -95,6 +98,16 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
95
98
  end
96
99
  end
97
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
+
98
111
  def part_query(mime_type)
99
112
  request.query_parameters.merge(part: mime_type).to_query
100
113
  end
data/lib/rails/paths.rb CHANGED
@@ -105,8 +105,8 @@ module Rails
105
105
  private
106
106
  def filter_by(&block)
107
107
  all_paths.find_all(&block).flat_map { |path|
108
- paths = path.existent
109
- 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 }
110
110
  }.uniq
111
111
  end
112
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
@@ -20,22 +20,26 @@ module Rails
20
20
  def call(env)
21
21
  request = ActionDispatch::Request.new(env)
22
22
 
23
- if logger.respond_to?(:tagged)
24
- 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
25
25
  else
26
- call_app(request, env)
26
+ 0
27
27
  end
28
+
29
+ call_app(request, env)
28
30
  end
29
31
 
30
32
  private
31
33
  def call_app(request, env) # :doc:
34
+ logger_tag_pop_count = env["rails.rack_logger_tag_count"]
35
+
32
36
  instrumenter = ActiveSupport::Notifications.instrumenter
33
37
  handle = instrumenter.build_handle("request.action_dispatch", { request: request })
34
38
  handle.start
35
39
 
36
40
  logger.info { started_request_message(request) }
37
41
  status, headers, body = response = @app.call(env)
38
- body = ::Rack::BodyProxy.new(body, &handle.method(:finish))
42
+ body = ::Rack::BodyProxy.new(body) { finish_request_instrumentation(handle, logger_tag_pop_count) }
39
43
 
40
44
  if response.frozen?
41
45
  [status, headers, body]
@@ -44,10 +48,8 @@ module Rails
44
48
  response
45
49
  end
46
50
  rescue Exception
47
- handle.finish
51
+ finish_request_instrumentation(handle, logger_tag_pop_count)
48
52
  raise
49
- ensure
50
- ActiveSupport::LogSubscriber.flush_all!
51
53
  end
52
54
 
53
55
  # Started GET "/session/new" for 127.0.0.1 at 2012-09-26 14:51:42 -0700
@@ -75,6 +77,12 @@ module Rails
75
77
  def logger
76
78
  Rails.logger
77
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
78
86
  end
79
87
  end
80
88
  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
data/lib/rails/railtie.rb CHANGED
@@ -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
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  namespace :app do
4
- desc "Update configs and some other initially generated files (or use just update:configs or update:bin)"
5
- task update: [ "update:configs", "update:bin", "update:active_storage", "update:upgrade_guide_info" ]
6
-
7
4
  desc "Apply the template supplied by LOCATION=(/path/to/template) or URL"
8
5
  task template: :environment do
9
6
  template = ENV["LOCATION"]
@@ -34,27 +31,4 @@ namespace :app do
34
31
  end
35
32
  end
36
33
  end
37
-
38
- namespace :update do
39
- require "rails/app_updater"
40
-
41
- # desc "Update config files from your current rails install"
42
- task :configs do
43
- Rails::AppUpdater.invoke_from_app_generator :create_boot_file
44
- Rails::AppUpdater.invoke_from_app_generator :update_config_files
45
- end
46
-
47
- # desc "Add new executables to the application bin/ directory"
48
- task :bin do
49
- Rails::AppUpdater.invoke_from_app_generator :update_bin_files
50
- end
51
-
52
- task :active_storage do
53
- Rails::AppUpdater.invoke_from_app_generator :update_active_storage
54
- end
55
-
56
- task :upgrade_guide_info do
57
- Rails::AppUpdater.invoke_from_app_generator :display_upgrade_guide_info
58
- end
59
- end
60
34
  end
@@ -7,7 +7,7 @@ namespace :tmp do
7
7
  tmp_dirs = [ "tmp/cache",
8
8
  "tmp/sockets",
9
9
  "tmp/pids",
10
- "tmp/cache/assets" ]
10
+ ]
11
11
 
12
12
  tmp_dirs.each { |d| directory d }
13
13
 
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html lang="en">
2
+ <html>
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
5
  <title><%= @page_title %></title>
@@ -61,14 +61,14 @@
61
61
  <body>
62
62
  <header>
63
63
  <dl>
64
- <% if @email.respond_to?(:smtp_envelope_from) && Array(@email.from) != Array(@email.smtp_envelope_from) %>
64
+ <% if Array(@email.from) != Array(@email.smtp_envelope_from) %>
65
65
  <dt>SMTP-From:</dt>
66
66
  <dd id="smtp_from"><%= @email.smtp_envelope_from %></dd>
67
67
  <% end %>
68
68
 
69
- <% if @email.respond_to?(:smtp_envelope_to) && @email.to != @email.smtp_envelope_to %>
69
+ <% if Set[*@email.to, *@email.cc, *@email.bcc] != Set[*@email.smtp_envelope_to] %>
70
70
  <dt>SMTP-To:</dt>
71
- <dd id="smtp_to"><%= @email.smtp_envelope_to %></dd>
71
+ <dd id="smtp_to"><%= @email.smtp_envelope_to.join(", ") %></dd>
72
72
  <% end %>
73
73
 
74
74
  <dt>From:</dt>
@@ -93,17 +93,21 @@
93
93
  <% end %>
94
94
 
95
95
  <dt>Date:</dt>
96
- <dd id="date"><%= Time.current.rfc2822 %></dd>
96
+ <dd id="date"><%= @email.header['date'] || Time.current.rfc2822 %></dd>
97
97
 
98
98
  <dt>Subject:</dt>
99
99
  <dd><strong id="subject"><%= @email.subject %></strong></dd>
100
100
 
101
- <% unless @email.attachments.nil? || @email.attachments.empty? %>
101
+ <% if @attachments.any? || @inline_attachments.any? %>
102
102
  <dt>Attachments:</dt>
103
103
  <dd>
104
- <% @email.attachments.each do |a| %>
105
- <% filename = a.respond_to?(:original_filename) ? a.original_filename : a.filename %>
106
- <%= link_to filename, "data:application/octet-stream;charset=utf-8;base64,#{Base64.encode64(a.body.to_s)}", download: filename %>
104
+ <% @attachments.each do |filename, attachment| %>
105
+ <%= link_to filename, attachment_url(attachment), download: filename %>
106
+ <% end %>
107
+
108
+ <% if @inline_attachments.any? %>
109
+ (Inline: <% @inline_attachments.each do |filename, attachment| %>
110
+ <%= link_to filename, attachment_url(attachment), download: filename %><% end %>)
107
111
  <% end %>
108
112
  </dd>
109
113
  <% end %>
@@ -1,11 +1,12 @@
1
- <% ruby_on_rails_logo_favicon_data_uri = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIwcHgiIGhlaWdodD0iMzIwcHgiIHZpZXdCb3g9IjAgMCAzMjAgMzIwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPHRpdGxlPkljb248L3RpdGxlPgogICAgPGcgaWQ9Ikljb24iIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJSdWJ5LU9uLVJhaWxzLUxvZ28iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDUuMDAwMDAwLCAyMC4wMDAwMDApIiBmaWxsPSIjRDgxRTAwIj4KICAgICAgICAgICAgPHBhdGggZD0iTTIxLjkzMzA3MDYsMjg1IEwxNjguMTc1NDI2LDI4NSBDMTQ3Ljk0MDg1OCwxNTAuNjkxNzA2IDE5Ni44ODIzODMsNjYuMzE0MjkwMiAzMTUsMzEuODY3NzUzNiBDMzE1LDIxLjc4NTEyODQgMzE1LDMxLjg2Nzc1MzYgMzE1LDIxLjc4NTEyODQgQzE2MS4yNTI4MywyNC45MTE2Mjc4IDYzLjU2Mzg1MzMsMTEyLjY0OTkxOCAyMS45MzMwNzA2LDI4NSBaIiBpZD0iUGF0aCIvPgogICAgICAgICAgICA8cG9seWdvbiBpZD0iUGF0aCIgcG9pbnRzPSI0MC40MDgyNjQzIDE4NS45MTU3MSAxMi43MzI2NDk0IDE3NC40MDE2NjMgLTEuNDIxMDg1NDdlLTE0IDIwNS40NDI3MSAyOS41NzExOTY2IDIxNi42NDcxMTUiLz4KICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIHBvaW50cz0iMTgwLjQ3MzEwMiAyNjguMDczNjQzIDIwNC45MzYwMTYgMjc2LjQxMDk2NiAyMDQuOTM2MDE2IDI1NC41MDg2NzMgMTgwLjQ4OTY0NCAyNDQuMzM4MTA3Ii8+CiAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJQYXRoIiBwb2ludHM9IjEwMC41ODk1MTkgOTcuMjI4NzYwNiA3Ni42ODQwMTU2IDc5LjE2ODcwMjEgNTUuMjQ0MDc5MSAxMDAuMTgzMTA1IDgxLjUxNDMyMzkgMTE3LjQzMzcyNSIvPgogICAgICAgICAgICA8cG9seWdvbiBpZD0iUGF0aCIgcG9pbnRzPSIxODQuNTc1Njc5IDE4NC44OTYyOTUgMjA3Ljk1MjAzIDIwMC4yNDY2MSAyMTEuNzI3NzI5IDE4MS4yMDUyNjYgMTg5Ljg2MzY1MyAxNjQuNjg3NDYiLz4KICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIHBvaW50cz0iMjYxLjczNDAxIDY1Ljg5NTk0NDYgMjY5LjM1NDIzNCA4Mi4zMjk1NCAyODUuMzE4MjU2IDcyLjcwNDg1OTYgMjc4LjMxMDEyOSA1Ni45ODI5ODk1Ii8+CiAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJQYXRoIiBwb2ludHM9IjI2MS45MTM3IDE2LjE4NDU0NzMgMjU1LjU5ODQ3OSA3LjEwNTQyNzM2ZS0xNSAyMzIuNzk2MDIgMy40ODg5NjMyMyAyNDAuNDYzODczIDIwLjAyNTI3MjUiLz4KICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIHBvaW50cz0iMjExLjkzNDExOSAxMTEuNTgwNjc1IDIyNi43MjI1NDcgMTI3Ljc5MjYwMSAyMzguMDIzOTI1IDExMy45MDM3MTUgMjIzLjQ2ODM3NSA5Ni41NDY4Njg1Ii8+CiAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJQYXRoIiBwb2ludHM9IjE3OS42ODY4NTggMzguNDk1MjIxOCAxNjQuNjQxOTMxIDIwLjAyNTI3MjUgMTM5Ljg0NzYyIDMyLjU1NTI5OTIgMTU2LjYwMTMyNCA1MC45MjE2NzUzIi8+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=" %>
2
1
  <!DOCTYPE html>
3
2
  <html>
4
3
  <head>
5
4
  <title>Ruby on Rails <%= Rails.version %></title>
6
5
  <meta charset="utf-8">
7
6
  <meta name="viewport" content="width=device-width">
8
- <link rel="icon" href="<%= ruby_on_rails_logo_favicon_data_uri %>" />
7
+
8
+ <link rel="icon" href="/icon.png" type="image/png">
9
+ <link rel="apple-touch-icon" href="/icon.png" sizes="512x512">
9
10
 
10
11
  <style type="text/css">
11
12
  * {
@@ -84,6 +85,7 @@
84
85
 
85
86
  <ul>
86
87
  <li><strong>Rails version:</strong> <%= Rails.version %></li>
88
+ <li><strong>Rack version:</strong> <%= Rack.release %></li>
87
89
  <li><strong>Ruby version:</strong> <%= RUBY_DESCRIPTION %></li>
88
90
  </ul>
89
91
  </body>
@@ -7,19 +7,17 @@
7
7
  abort("Abort testing: Your Rails environment is running in production mode!") if Rails.env.production?
8
8
 
9
9
  require "active_support/test_case"
10
- require "action_controller"
11
- require "action_controller/test_case"
12
- require "action_dispatch/testing/integration"
13
10
  require "rails/generators/test_case"
14
-
15
11
  require "active_support/testing/autorun"
16
12
 
17
13
  require "rails/testing/maintain_test_schema"
18
14
 
19
15
  if defined?(ActiveRecord::Base)
16
+ require "active_record/testing/query_assertions"
20
17
  ActiveSupport.on_load(:active_support_test_case) do
21
18
  include ActiveRecord::TestDatabases
22
19
  include ActiveRecord::TestFixtures
20
+ include ActiveRecord::Assertions::QueryAssertions
23
21
 
24
22
  self.fixture_paths << "#{Rails.root}/test/fixtures/"
25
23
  self.file_fixture_path = "#{Rails.root}/test/fixtures/files"
@@ -8,6 +8,13 @@ module Rails
8
8
  class_attribute :app_root
9
9
  class_attribute :executable, default: "bin/rails test"
10
10
 
11
+ def prerecord(test_class, test_name)
12
+ super
13
+ if options[:verbose]
14
+ io.print "%s#%s = " % [test_class.name, test_name]
15
+ end
16
+ end
17
+
11
18
  def record(result)
12
19
  super
13
20
 
@@ -69,8 +76,7 @@ module Rails
69
76
  end
70
77
 
71
78
  def format_line(result)
72
- klass = result.respond_to?(:klass) ? result.klass : result.class
73
- "%s#%s = %.2f s = %s" % [klass, result.name, result.time, result.result_code]
79
+ "%.2f s = %s" % [result.time, result.result_code]
74
80
  end
75
81
 
76
82
  def format_rerun_snippet(result)
@@ -9,6 +9,15 @@ require "rails/test_unit/test_parser"
9
9
 
10
10
  module Rails
11
11
  module TestUnit
12
+ class InvalidTestError < StandardError
13
+ def initialize(path, suggestion)
14
+ super(<<~MESSAGE.squish)
15
+ Could not load test file: #{path}.
16
+ #{suggestion}
17
+ MESSAGE
18
+ end
19
+ end
20
+
12
21
  class Runner
13
22
  TEST_FOLDERS = [:models, :helpers, :channels, :controllers, :mailers, :integration, :jobs, :mailboxes]
14
23
  PATH_ARGUMENT_PATTERN = %r"^(?!/.+/$)[.\w]*[/\\]"
@@ -48,7 +57,22 @@ module Rails
48
57
  def load_tests(argv)
49
58
  patterns = extract_filters(argv)
50
59
  tests = list_tests(patterns)
51
- tests.to_a.each { |path| require File.expand_path(path) }
60
+ tests.to_a.each do |path|
61
+ abs_path = File.expand_path(path)
62
+ require abs_path
63
+ rescue LoadError => exception
64
+ if exception.path == abs_path
65
+ all_tests = list_tests([default_test_glob])
66
+ corrections = DidYouMean::SpellChecker.new(dictionary: all_tests).correct(path)
67
+
68
+ if corrections.empty?
69
+ raise exception
70
+ end
71
+ raise InvalidTestError.new(path, DidYouMean::Formatter.message_for(corrections))
72
+ else
73
+ raise
74
+ end
75
+ end
52
76
  end
53
77
 
54
78
  def compose_filter(runnable, filter)
@@ -87,7 +111,7 @@ module Rails
87
111
  end
88
112
 
89
113
  def default_test_exclude_glob
90
- ENV["DEFAULT_TEST_EXCLUDE"] || "test/{system,dummy}/**/*_test.rb"
114
+ ENV["DEFAULT_TEST_EXCLUDE"] || "test/{system,dummy,fixtures}/**/*_test.rb"
91
115
  end
92
116
 
93
117
  def regexp_filter?(arg)
@@ -1,5 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ begin
4
+ require "prism"
5
+ rescue LoadError
6
+ # If Prism isn't available (because of using an older Ruby version) then we'll
7
+ # define a fallback parser using ripper.
8
+ end
9
+
10
+ if defined?(Prism)
11
+ module Rails
12
+ module TestUnit
13
+ # Parse a test file to extract the line ranges of all tests in both
14
+ # method-style (def test_foo) and declarative-style (test "foo" do)
15
+ module TestParser
16
+ # Helper to translate a method object into the path and line range where
17
+ # the method was defined.
18
+ def self.definition_for(method)
19
+ filepath, start_line = method.source_location
20
+ queue = [Prism.parse_file(filepath).value]
21
+
22
+ while (node = queue.shift)
23
+ case node.type
24
+ when :def_node
25
+ if node.location.start_line == start_line
26
+ return [filepath, start_line..node.location.end_line]
27
+ end
28
+ when :call_node
29
+ if node.location.start_line == start_line
30
+ return [filepath, start_line..node.location.end_line]
31
+ end
32
+ end
33
+
34
+ queue.concat(node.compact_child_nodes)
35
+ end
36
+
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ # If we have Prism, then we don't need to define the fallback parser using
44
+ # ripper.
45
+ return
46
+ end
47
+
3
48
  require "ripper"
4
49
 
5
50
  module Rails
data/lib/rails.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rails/ruby_version_check"
4
-
5
3
  require "pathname"
6
4
 
7
5
  require "active_support"
@@ -24,17 +22,21 @@ silence_warnings do
24
22
  Encoding.default_internal = Encoding::UTF_8
25
23
  end
26
24
 
27
- # :include: railties/README.rdoc
25
+ # :include: ../README.rdoc
28
26
  module Rails
29
27
  extend ActiveSupport::Autoload
30
28
  extend ActiveSupport::Benchmarkable
31
29
 
32
- autoload :HealthController
33
30
  autoload :Info
34
31
  autoload :InfoController
35
32
  autoload :MailersController
36
33
  autoload :WelcomeController
37
34
 
35
+ eager_autoload do
36
+ autoload :HealthController
37
+ autoload :PwaController
38
+ end
39
+
38
40
  class << self
39
41
  @application = @app_class = nil
40
42
 
@@ -69,6 +71,7 @@ module Rails
69
71
  # Rails.env # => "development"
70
72
  # Rails.env.development? # => true
71
73
  # Rails.env.production? # => false
74
+ # Rails.env.local? # => true true for "development" and "test", false for anything else
72
75
  def env
73
76
  @_env ||= ActiveSupport::EnvironmentInquirer.new(ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || "development")
74
77
  end