railties 7.0.8.7 → 7.2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +210 -272
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.md +99 -0
  5. data/README.rdoc +4 -4
  6. data/lib/minitest/rails_plugin.rb +67 -1
  7. data/lib/rails/all.rb +1 -3
  8. data/lib/rails/api/task.rb +39 -6
  9. data/lib/rails/application/bootstrap.rb +28 -10
  10. data/lib/rails/application/configuration.rb +228 -72
  11. data/lib/rails/application/default_middleware_stack.rb +8 -2
  12. data/lib/rails/application/dummy_config.rb +19 -0
  13. data/lib/rails/application/finisher.rb +50 -33
  14. data/lib/rails/application.rb +117 -76
  15. data/lib/rails/backtrace_cleaner.rb +19 -4
  16. data/lib/rails/cli.rb +5 -3
  17. data/lib/rails/command/actions.rb +10 -12
  18. data/lib/rails/command/base.rb +55 -53
  19. data/lib/rails/command/environment_argument.rb +32 -16
  20. data/lib/rails/command/helpers/editor.rb +17 -12
  21. data/lib/rails/command.rb +84 -33
  22. data/lib/rails/commands/about/about_command.rb +14 -0
  23. data/lib/rails/commands/app/update_command.rb +102 -0
  24. data/lib/rails/commands/application/application_command.rb +2 -0
  25. data/lib/rails/commands/boot/boot_command.rb +14 -0
  26. data/lib/rails/commands/console/console_command.rb +11 -30
  27. data/lib/rails/commands/console/irb_console.rb +146 -0
  28. data/lib/rails/commands/credentials/USAGE +53 -55
  29. data/lib/rails/commands/credentials/credentials_command/diffing.rb +5 -3
  30. data/lib/rails/commands/credentials/credentials_command.rb +64 -70
  31. data/lib/rails/commands/db/system/change/change_command.rb +2 -1
  32. data/lib/rails/commands/dbconsole/dbconsole_command.rb +32 -131
  33. data/lib/rails/commands/destroy/destroy_command.rb +3 -2
  34. data/lib/rails/commands/dev/dev_command.rb +1 -6
  35. data/lib/rails/commands/devcontainer/devcontainer_command.rb +39 -0
  36. data/lib/rails/commands/encrypted/USAGE +15 -20
  37. data/lib/rails/commands/encrypted/encrypted_command.rb +46 -35
  38. data/lib/rails/commands/gem_help/USAGE +16 -0
  39. data/lib/rails/commands/gem_help/gem_help_command.rb +13 -0
  40. data/lib/rails/commands/generate/generate_command.rb +2 -2
  41. data/lib/rails/commands/help/USAGE +13 -13
  42. data/lib/rails/commands/help/help_command.rb +21 -2
  43. data/lib/rails/commands/initializers/initializers_command.rb +1 -4
  44. data/lib/rails/commands/middleware/middleware_command.rb +17 -0
  45. data/lib/rails/commands/new/new_command.rb +2 -0
  46. data/lib/rails/commands/notes/notes_command.rb +2 -1
  47. data/lib/rails/commands/plugin/plugin_command.rb +2 -0
  48. data/lib/rails/commands/rake/rake_command.rb +25 -22
  49. data/lib/rails/commands/restart/restart_command.rb +14 -0
  50. data/lib/rails/commands/routes/routes_command.rb +13 -1
  51. data/lib/rails/commands/runner/USAGE +14 -12
  52. data/lib/rails/commands/runner/runner_command.rb +42 -19
  53. data/lib/rails/commands/secret/secret_command.rb +13 -0
  54. data/lib/rails/commands/server/server_command.rb +37 -34
  55. data/lib/rails/commands/test/USAGE +14 -0
  56. data/lib/rails/commands/test/test_command.rb +58 -14
  57. data/lib/rails/commands/unused_routes/unused_routes_command.rb +75 -0
  58. data/lib/rails/commands/version/version_command.rb +1 -0
  59. data/lib/rails/configuration.rb +15 -6
  60. data/lib/rails/console/app.rb +5 -35
  61. data/lib/rails/console/helpers.rb +5 -16
  62. data/lib/rails/console/methods.rb +23 -0
  63. data/lib/rails/deprecator.rb +7 -0
  64. data/lib/rails/engine/configuration.rb +50 -6
  65. data/lib/rails/engine.rb +53 -25
  66. data/lib/rails/gem_version.rb +4 -4
  67. data/lib/rails/generators/actions.rb +6 -15
  68. data/lib/rails/generators/active_model.rb +28 -14
  69. data/lib/rails/generators/app_base.rb +382 -88
  70. data/lib/rails/generators/app_name.rb +3 -14
  71. data/lib/rails/generators/base.rb +21 -9
  72. data/lib/rails/generators/database.rb +231 -35
  73. data/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt +1 -1
  74. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  75. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  76. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  77. data/lib/rails/generators/generated_attribute.rb +38 -1
  78. data/lib/rails/generators/migration.rb +4 -5
  79. data/lib/rails/generators/model_helpers.rb +2 -1
  80. data/lib/rails/generators/rails/app/USAGE +22 -6
  81. data/lib/rails/generators/rails/app/app_generator.rb +135 -86
  82. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +110 -0
  83. data/lib/rails/generators/rails/app/templates/Gemfile.tt +19 -21
  84. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  85. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +8 -1
  86. data/lib/rails/generators/rails/app/templates/app/views/layouts/mailer.html.erb.tt +1 -1
  87. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  88. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  89. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  90. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  91. data/lib/rails/generators/rails/app/templates/bin/setup.tt +15 -2
  92. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +6 -17
  93. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  94. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +11 -6
  95. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +10 -3
  96. data/lib/rails/generators/rails/app/templates/config/databases/{jdbcmysql.yml.tt → trilogy.yml.tt} +12 -7
  97. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +25 -8
  98. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +40 -28
  99. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +20 -13
  100. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +3 -1
  101. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +2 -2
  102. data/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt +1 -1
  103. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +4 -4
  104. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +70 -0
  105. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +11 -9
  106. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +11 -13
  107. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +25 -34
  108. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +11 -1
  109. data/lib/rails/generators/rails/app/templates/db/seeds.rb.tt +6 -4
  110. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +15 -0
  111. data/lib/rails/generators/rails/app/templates/dockerignore.tt +56 -0
  112. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +138 -0
  113. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  114. data/lib/rails/generators/rails/app/templates/gitignore.tt +7 -11
  115. data/lib/rails/generators/rails/app/templates/node-version.tt +1 -0
  116. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +66 -0
  117. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  118. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  119. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  120. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  121. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +10 -8
  122. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +9 -7
  123. data/lib/rails/generators/rails/application_record/application_record_generator.rb +4 -0
  124. data/lib/rails/generators/rails/benchmark/benchmark_generator.rb +2 -1
  125. data/lib/rails/generators/rails/controller/USAGE +12 -4
  126. data/lib/rails/generators/rails/controller/controller_generator.rb +6 -1
  127. data/lib/rails/generators/rails/controller/templates/controller.rb.tt +1 -1
  128. data/lib/rails/generators/rails/credentials/credentials_generator.rb +29 -24
  129. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +8 -0
  130. data/lib/rails/generators/rails/db/system/change/change_generator.rb +146 -5
  131. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +166 -0
  132. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  133. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  134. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  135. data/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb +1 -2
  136. data/lib/rails/generators/rails/migration/USAGE +21 -11
  137. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  138. data/lib/rails/generators/rails/model/model_generator.rb +4 -0
  139. data/lib/rails/generators/rails/plugin/USAGE +17 -6
  140. data/lib/rails/generators/rails/plugin/plugin_generator.rb +45 -22
  141. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  142. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +7 -3
  143. data/lib/rails/generators/rails/plugin/templates/MIT-LICENSE.tt +1 -1
  144. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  145. data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +1 -17
  146. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  147. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  148. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  149. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +0 -2
  150. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  151. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  152. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +5 -5
  153. data/lib/rails/generators/rails/resource/resource_generator.rb +6 -0
  154. data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +2 -1
  155. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +1 -1
  156. data/lib/rails/generators/test_case.rb +2 -2
  157. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  158. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  159. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +16 -2
  160. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  161. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  162. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  163. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  164. data/lib/rails/generators/testing/assertions.rb +20 -0
  165. data/lib/rails/generators/testing/{behaviour.rb → behavior.rb} +8 -4
  166. data/lib/rails/generators.rb +12 -16
  167. data/lib/rails/health_controller.rb +55 -0
  168. data/lib/rails/info.rb +3 -3
  169. data/lib/rails/info_controller.rb +33 -11
  170. data/lib/rails/mailers_controller.rb +29 -6
  171. data/lib/rails/paths.rb +15 -12
  172. data/lib/rails/pwa_controller.rb +15 -0
  173. data/lib/rails/rack/logger.rb +27 -16
  174. data/lib/rails/rackup/server.rb +15 -0
  175. data/lib/rails/railtie/configurable.rb +2 -2
  176. data/lib/rails/railtie/configuration.rb +14 -1
  177. data/lib/rails/railtie.rb +33 -34
  178. data/lib/rails/source_annotation_extractor.rb +67 -18
  179. data/lib/rails/tasks/engine.rake +8 -8
  180. data/lib/rails/tasks/framework.rake +2 -34
  181. data/lib/rails/tasks/log.rake +1 -1
  182. data/lib/rails/tasks/misc.rake +3 -14
  183. data/lib/rails/tasks/statistics.rake +5 -4
  184. data/lib/rails/tasks/tmp.rake +6 -6
  185. data/lib/rails/tasks/zeitwerk.rake +15 -35
  186. data/lib/rails/tasks.rb +0 -2
  187. data/lib/rails/templates/layouts/application.html.erb +1 -1
  188. data/lib/rails/templates/rails/mailers/email.html.erb +44 -8
  189. data/lib/rails/templates/rails/mailers/index.html.erb +14 -7
  190. data/lib/rails/templates/rails/mailers/mailer.html.erb +11 -5
  191. data/lib/rails/templates/rails/welcome/index.html.erb +5 -2
  192. data/lib/rails/test_help.rb +11 -18
  193. data/lib/rails/test_unit/line_filtering.rb +1 -1
  194. data/lib/rails/test_unit/reporter.rb +14 -4
  195. data/lib/rails/test_unit/runner.rb +62 -20
  196. data/lib/rails/test_unit/test_parser.rb +133 -0
  197. data/lib/rails/test_unit/testing.rake +13 -33
  198. data/lib/rails/testing/maintain_test_schema.rb +16 -0
  199. data/lib/rails/version.rb +1 -1
  200. data/lib/rails/zeitwerk_checker.rb +15 -0
  201. data/lib/rails.rb +20 -17
  202. metadata +87 -40
  203. data/RDOC_MAIN.rdoc +0 -97
  204. data/lib/rails/app_updater.rb +0 -40
  205. data/lib/rails/application/dummy_erb_compiler.rb +0 -18
  206. data/lib/rails/commands/secrets/USAGE +0 -66
  207. data/lib/rails/commands/secrets/secrets_command.rb +0 -65
  208. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  209. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  210. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  211. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  212. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  213. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +0 -143
  214. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  215. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  216. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  217. data/lib/rails/generators/rails/model/USAGE +0 -113
  218. data/lib/rails/ruby_version_check.rb +0 -15
  219. data/lib/rails/secrets.rb +0 -110
  220. data/lib/rails/tasks/middleware.rake +0 -9
  221. data/lib/rails/tasks/restart.rake +0 -9
@@ -44,6 +44,13 @@
44
44
  content: "\00a0"; //  
45
45
  }
46
46
 
47
+ th {
48
+ font-weight: inherit;
49
+ color: #7f7f7f;
50
+ text-align: right;
51
+ white-space: nowrap;
52
+ }
53
+
47
54
  iframe {
48
55
  border: 0;
49
56
  width: 100%;
@@ -54,14 +61,14 @@
54
61
  <body>
55
62
  <header>
56
63
  <dl>
57
- <% 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) %>
58
65
  <dt>SMTP-From:</dt>
59
66
  <dd id="smtp_from"><%= @email.smtp_envelope_from %></dd>
60
67
  <% end %>
61
68
 
62
- <% 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] %>
63
70
  <dt>SMTP-To:</dt>
64
- <dd id="smtp_to"><%= @email.smtp_envelope_to %></dd>
71
+ <dd id="smtp_to"><%= @email.smtp_envelope_to.join(", ") %></dd>
65
72
  <% end %>
66
73
 
67
74
  <dt>From:</dt>
@@ -80,18 +87,27 @@
80
87
  <dd id="cc"><%= @email.header['cc'] %></dd>
81
88
  <% end %>
82
89
 
90
+ <% if @email.bcc %>
91
+ <dt>BCC:</dt>
92
+ <dd id="bcc"><%= @email.header['bcc'] %></dd>
93
+ <% end %>
94
+
83
95
  <dt>Date:</dt>
84
- <dd id="date"><%= Time.current.rfc2822 %></dd>
96
+ <dd id="date"><%= @email.header['date'] || Time.current.rfc2822 %></dd>
85
97
 
86
98
  <dt>Subject:</dt>
87
99
  <dd><strong id="subject"><%= @email.subject %></strong></dd>
88
100
 
89
- <% unless @email.attachments.nil? || @email.attachments.empty? %>
101
+ <% if @attachments.any? || @inline_attachments.any? %>
90
102
  <dt>Attachments:</dt>
91
103
  <dd>
92
- <% @email.attachments.each do |a| %>
93
- <% filename = a.respond_to?(:original_filename) ? a.original_filename : a.filename %>
94
- <%= 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 %>)
95
111
  <% end %>
96
112
  </dd>
97
113
  <% end %>
@@ -120,6 +136,26 @@
120
136
  </select>
121
137
  </dd>
122
138
  <% end %>
139
+
140
+ <% unless @email.header_fields.nil? || @email.header_fields.empty? %>
141
+ <dt>Headers:</dt>
142
+ <dd>
143
+ <details>
144
+ <summary>Show all headers</summary>
145
+ <table>
146
+ <% @email.header_fields.each do |field| %>
147
+ <tr>
148
+ <th><%= field.name %>:</th>
149
+ <td><%= field.value %></td>
150
+ </tr>
151
+ <% end %>
152
+ </table>
153
+ </details>
154
+ </dd>
155
+ <% end %>
156
+
157
+ <dt>EML File:</dt>
158
+ <dd><%= link_to "Download", action: :download %></dd>
123
159
  </dl>
124
160
  </header>
125
161
 
@@ -1,8 +1,15 @@
1
- <% @previews.each do |preview| %>
2
- <h3><%= link_to preview.preview_name.titleize, url_for(controller: "rails/mailers", action: "preview", path: preview.preview_name) %></h3>
3
- <ul>
4
- <% preview.emails.each do |email| %>
5
- <li><%= link_to email, url_for(controller: "rails/mailers", action: "preview", path: "#{preview.preview_name}/#{email}") %></li>
6
- <% end %>
7
- </ul>
1
+ <h1><%= @page_title %></h1>
2
+
3
+ <% if @previews.any? %>
4
+ <% @previews.each do |preview| %>
5
+ <h3><%= link_to preview.preview_name.titleize, url_for(controller: "rails/mailers", action: "preview", path: preview.preview_name) %></h3>
6
+ <ul>
7
+ <% preview.emails.each do |email| %>
8
+ <li><%= link_to email, url_for(controller: "rails/mailers", action: "preview", path: "#{preview.preview_name}/#{email}") %></li>
9
+ <% end %>
10
+ </ul>
11
+ <% end %>
12
+ <% else %>
13
+ <p>You have not defined any Action Mailer Previews.</p>
14
+ <p>Read <%= link_to "Action Mailer Basics", "https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails" %> to learn how to define your first.</p>
8
15
  <% end %>
@@ -1,6 +1,12 @@
1
- <h3><%= @preview.preview_name.titleize %></h3>
2
- <ul>
3
- <% @preview.emails.each do |email| %>
4
- <li><%= link_to email, url_for(controller: "rails/mailers", action: "preview", path: "#{@preview.preview_name}/#{email}") %></li>
1
+ <h1><%= @page_title %></h1>
2
+
3
+ <% if @preview.emails.any? %>
4
+ <ul>
5
+ <% @preview.emails.each do |email| %>
6
+ <li><%= link_to email, url_for(controller: "rails/mailers", action: "preview", path: "#{@preview.preview_name}/#{email}") %></li>
7
+ <% end %>
8
+ </ul>
9
+ <% else %>
10
+ <p>You have not defined any actions for <%= @preview %>.</p>
11
+ <p>Read <%= link_to "Action Mailer Basics", "https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails" %> to learn how to define your first.</p>
5
12
  <% end %>
6
- </ul>
@@ -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
  * {
@@ -50,6 +51,7 @@
50
51
  border-radius: 100%;
51
52
  display: flex;
52
53
  transition: background 0.25s cubic-bezier(0.33, 1, 0.68, 1);
54
+ filter: drop-shadow(0 20px 13px rgb(0 0 0 / 0.03)) drop-shadow(0 8px 5px rgb(0 0 0 / 0.08));
53
55
  }
54
56
 
55
57
  nav a:hover {
@@ -83,6 +85,7 @@
83
85
 
84
86
  <ul>
85
87
  <li><strong>Rails version:</strong> <%= Rails.version %></li>
88
+ <li><strong>Rack version:</strong> <%= Rack.release %></li>
86
89
  <li><strong>Ruby version:</strong> <%= RUBY_DESCRIPTION %></li>
87
90
  </ul>
88
91
  </body>
@@ -1,35 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :enddoc:
4
+
3
5
  # Make double-sure the RAILS_ENV is not set to production,
4
6
  # so fixtures aren't loaded into that environment
5
7
  abort("Abort testing: Your Rails environment is running in production mode!") if Rails.env.production?
6
8
 
7
9
  require "active_support/test_case"
8
- require "action_controller"
9
- require "action_controller/test_case"
10
- require "action_dispatch/testing/integration"
11
10
  require "rails/generators/test_case"
12
-
13
11
  require "active_support/testing/autorun"
14
12
 
15
- if defined?(ActiveRecord::Base)
16
- begin
17
- ActiveRecord::Migration.maintain_test_schema!
18
- rescue ActiveRecord::PendingMigrationError => e
19
- puts e.to_s.strip
20
- exit 1
21
- end
13
+ require "rails/testing/maintain_test_schema"
22
14
 
15
+ if defined?(ActiveRecord::Base)
16
+ require "active_record/testing/query_assertions"
23
17
  ActiveSupport.on_load(:active_support_test_case) do
24
18
  include ActiveRecord::TestDatabases
25
19
  include ActiveRecord::TestFixtures
20
+ include ActiveRecord::Assertions::QueryAssertions
26
21
 
27
- self.fixture_path = "#{Rails.root}/test/fixtures/"
28
- self.file_fixture_path = fixture_path + "files"
22
+ self.fixture_paths << "#{Rails.root}/test/fixtures/"
23
+ self.file_fixture_path = "#{Rails.root}/test/fixtures/files"
29
24
  end
30
25
 
31
26
  ActiveSupport.on_load(:action_dispatch_integration_test) do
32
- self.fixture_path = ActiveSupport::TestCase.fixture_path
27
+ self.fixture_paths += ActiveSupport::TestCase.fixture_paths
33
28
  end
34
29
  else
35
30
  ActiveSupport.on_load(:active_support_test_case) do
@@ -37,17 +32,15 @@ else
37
32
  end
38
33
  end
39
34
 
40
- # :enddoc:
41
-
42
35
  ActiveSupport.on_load(:action_controller_test_case) do
43
- def before_setup # :nodoc:
36
+ def before_setup
44
37
  @routes = Rails.application.routes
45
38
  super
46
39
  end
47
40
  end
48
41
 
49
42
  ActiveSupport.on_load(:action_dispatch_integration_test) do
50
- def before_setup # :nodoc:
43
+ def before_setup
51
44
  @routes = Rails.application.routes
52
45
  super
53
46
  end
@@ -5,7 +5,7 @@ require "rails/test_unit/runner"
5
5
  module Rails
6
6
  module LineFiltering # :nodoc:
7
7
  def run(reporter, options = {})
8
- options[:filter] = Rails::TestUnit::Runner.compose_filter(self, options[:filter])
8
+ options = options.merge(filter: Rails::TestUnit::Runner.compose_filter(self, options[:filter]))
9
9
 
10
10
  super
11
11
  end
@@ -6,7 +6,14 @@ require "minitest"
6
6
  module Rails
7
7
  class TestUnitReporter < Minitest::StatisticsReporter
8
8
  class_attribute :app_root
9
- class_attribute :executable, default: "rails test"
9
+ class_attribute :executable, default: "bin/rails test"
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
10
17
 
11
18
  def record(result)
12
19
  super
@@ -52,7 +59,11 @@ module Rails
52
59
  end
53
60
 
54
61
  def relative_path_for(file)
55
- file.sub(/^#{app_root}\/?/, "")
62
+ if app_root
63
+ file.sub(/^#{app_root}\/?/, "")
64
+ else
65
+ file
66
+ end
56
67
  end
57
68
 
58
69
  private
@@ -65,8 +76,7 @@ module Rails
65
76
  end
66
77
 
67
78
  def format_line(result)
68
- klass = result.respond_to?(:klass) ? result.klass : result.class
69
- "%s#%s = %.2f s = %s" % [klass, result.name, result.time, result.result_code]
79
+ "%.2f s = %s" % [result.time, result.result_code]
70
80
  end
71
81
 
72
82
  def format_rerun_snippet(result)
@@ -1,14 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "shellwords"
4
- require "method_source"
5
4
  require "rake/file_list"
6
5
  require "active_support"
7
6
  require "active_support/core_ext/module/attribute_accessors"
7
+ require "active_support/core_ext/range"
8
+ require "rails/test_unit/test_parser"
8
9
 
9
10
  module Rails
10
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
+
11
21
  class Runner
22
+ TEST_FOLDERS = [:models, :helpers, :channels, :controllers, :mailers, :integration, :jobs, :mailboxes]
23
+ PATH_ARGUMENT_PATTERN = %r"^(?!/.+/$)[.\w]*[/\\]"
12
24
  mattr_reader :filters, default: []
13
25
 
14
26
  class << self
@@ -30,9 +42,9 @@ module Rails
30
42
  $VERBOSE = argv.delete_at(w_index) if w_index
31
43
  end
32
44
 
33
- def rake_run(argv = [])
45
+ def run_from_rake(test_command, argv = [])
34
46
  # Ensure the tests run during the Rake Task action, not when the process exits
35
- success = system("rails", "test", *argv, *Shellwords.split(ENV["TESTOPTS"] || ""))
47
+ success = system("rails", test_command, *argv, *Shellwords.split(ENV["TESTOPTS"] || ""))
36
48
  success || exit(false)
37
49
  end
38
50
 
@@ -43,11 +55,29 @@ module Rails
43
55
  end
44
56
 
45
57
  def load_tests(argv)
46
- tests = list_tests(argv)
47
- tests.to_a.each { |path| require File.expand_path(path) }
58
+ patterns = extract_filters(argv)
59
+ tests = list_tests(patterns)
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
48
76
  end
49
77
 
50
78
  def compose_filter(runnable, filter)
79
+ filter = normalize_declarative_test_filter(filter)
80
+
51
81
  if filters.any? { |_, lines| lines.any? }
52
82
  CompositeFilter.new(runnable, filter, filters)
53
83
  else
@@ -59,11 +89,11 @@ module Rails
59
89
  def extract_filters(argv)
60
90
  # Extract absolute and relative paths but skip -n /.*/ regexp filters.
61
91
  argv.filter_map do |path|
62
- next unless path_argument?(path) && !regexp_filter?(path)
92
+ next unless path_argument?(path)
63
93
 
64
94
  path = path.tr("\\", "/")
65
95
  case
66
- when /(:\d+)+$/.match?(path)
96
+ when /(:\d+(-\d+)?)+$/.match?(path)
67
97
  file, *lines = path.split(":")
68
98
  filters << [ file, lines ]
69
99
  file
@@ -81,7 +111,7 @@ module Rails
81
111
  end
82
112
 
83
113
  def default_test_exclude_glob
84
- ENV["DEFAULT_TEST_EXCLUDE"] || "test/{system,dummy}/**/*_test.rb"
114
+ ENV["DEFAULT_TEST_EXCLUDE"] || "test/{system,dummy,fixtures}/**/*_test.rb"
85
115
  end
86
116
 
87
117
  def regexp_filter?(arg)
@@ -89,16 +119,27 @@ module Rails
89
119
  end
90
120
 
91
121
  def path_argument?(arg)
92
- %r"^[/\\]?\w+[/\\]".match?(arg)
122
+ PATH_ARGUMENT_PATTERN.match?(arg)
93
123
  end
94
124
 
95
- def list_tests(argv)
96
- patterns = extract_filters(argv)
97
-
125
+ def list_tests(patterns)
98
126
  tests = Rake::FileList[patterns.any? ? patterns : default_test_glob]
99
127
  tests.exclude(default_test_exclude_glob) if patterns.empty?
100
128
  tests
101
129
  end
130
+
131
+ def normalize_declarative_test_filter(filter)
132
+ if filter.is_a?(String)
133
+ if regexp_filter?(filter)
134
+ # Minitest::Spec::DSL#it does not replace whitespace in method
135
+ # names, so match unmodified method names as well.
136
+ filter = filter.gsub(/\s+/, "_").delete_suffix("/") + "|" + filter.delete_prefix("/")
137
+ elsif !filter.start_with?("test_")
138
+ filter = "test_#{filter.gsub(/\s+/, "_")}"
139
+ end
140
+ end
141
+ filter
142
+ end
102
143
  end
103
144
  end
104
145
 
@@ -139,17 +180,21 @@ module Rails
139
180
  end
140
181
 
141
182
  class Filter # :nodoc:
142
- def initialize(runnable, file, line)
183
+ def initialize(runnable, file, line_or_range)
143
184
  @runnable, @file = runnable, File.expand_path(file)
144
- @line = line.to_i if line
185
+ if line_or_range
186
+ first, last = line_or_range.split("-").map(&:to_i)
187
+ last ||= first
188
+ @line_range = Range.new(first, last)
189
+ end
145
190
  end
146
191
 
147
192
  def ===(method)
148
193
  return unless @runnable.method_defined?(method)
149
194
 
150
- if @line
195
+ if @line_range
151
196
  test_file, test_range = definition_for(@runnable.instance_method(method))
152
- test_file == @file && test_range.include?(@line)
197
+ test_file == @file && @line_range.overlaps?(test_range)
153
198
  else
154
199
  @runnable.instance_method(method).source_location.first == @file
155
200
  end
@@ -157,10 +202,7 @@ module Rails
157
202
 
158
203
  private
159
204
  def definition_for(method)
160
- file, start_line = method.source_location
161
- end_line = method.source.count("\n") + start_line - 1
162
-
163
- return file, start_line..end_line
205
+ TestParser.definition_for(method)
164
206
  end
165
207
  end
166
208
  end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
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
+
48
+ require "ripper"
49
+
50
+ module Rails
51
+ module TestUnit
52
+ # Parse a test file to extract the line ranges of all tests in both
53
+ # method-style (def test_foo) and declarative-style (test "foo" do)
54
+ class TestParser < Ripper # :nodoc:
55
+ # Helper to translate a method object into the path and line range where
56
+ # the method was defined.
57
+ def self.definition_for(method_obj)
58
+ path, begin_line = method_obj.source_location
59
+ begins_to_ends = new(File.read(path), path).parse
60
+ return unless end_line = begins_to_ends[begin_line]
61
+ [path, (begin_line..end_line)]
62
+ end
63
+
64
+ def initialize(*)
65
+ # A hash mapping the 1-indexed line numbers that tests start on to where they end.
66
+ @begins_to_ends = {}
67
+ super
68
+ end
69
+
70
+ def parse
71
+ super
72
+ @begins_to_ends
73
+ end
74
+
75
+ # method test e.g. `def test_some_description`
76
+ # This event's first argument gets the `ident` node containing the method
77
+ # name, which we have overridden to return the line number of the ident
78
+ # instead.
79
+ def on_def(begin_line, *)
80
+ @begins_to_ends[begin_line] = lineno
81
+ end
82
+
83
+ # Everything past this point is to support declarative tests, which
84
+ # require more work to get right because of the many different ways
85
+ # methods can be invoked in ruby, all of which are parsed differently.
86
+ #
87
+ # The approach is just to store the current line number when the
88
+ # "test" method is called and pass it up the tree so it's available at
89
+ # the point when we also know the line where the associated block ends.
90
+
91
+ def on_method_add_block(begin_line, end_line)
92
+ if begin_line && end_line
93
+ @begins_to_ends[begin_line] = end_line
94
+ end
95
+ end
96
+
97
+ def on_command_call(*, begin_lineno, _args)
98
+ begin_lineno
99
+ end
100
+
101
+ def first_arg(arg, *)
102
+ arg
103
+ end
104
+
105
+ def just_lineno(*)
106
+ lineno
107
+ end
108
+
109
+ alias on_method_add_arg first_arg
110
+ alias on_command first_arg
111
+ alias on_stmts_add first_arg
112
+ alias on_arg_paren first_arg
113
+ alias on_bodystmt first_arg
114
+
115
+ alias on_ident just_lineno
116
+ alias on_do_block just_lineno
117
+ alias on_stmts_new just_lineno
118
+ alias on_brace_block just_lineno
119
+
120
+ def on_args_new
121
+ []
122
+ end
123
+
124
+ def on_args_add(parts, part)
125
+ parts << part
126
+ end
127
+
128
+ def on_args_add_block(args, *rest)
129
+ args.first
130
+ end
131
+ end
132
+ end
133
+ end
@@ -1,18 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem "minitest"
4
3
  require "minitest"
5
4
  require "rails/test_unit/runner"
6
5
 
7
6
  task default: :test
8
7
 
9
- desc "Runs all tests in test folder except system ones"
8
+ desc "Run all tests in test folder except system ones"
10
9
  task :test do
11
- if ENV.key?("TEST")
12
- Rails::TestUnit::Runner.rake_run([ENV["TEST"]])
13
- else
14
- Rails::TestUnit::Runner.rake_run
15
- end
10
+ Rails::TestUnit::Runner.run_from_rake("test", Array(ENV["TEST"]))
16
11
  end
17
12
 
18
13
  namespace :test do
@@ -23,37 +18,22 @@ namespace :test do
23
18
 
24
19
  task run: %w[test]
25
20
 
26
- desc "Run tests quickly, but also reset db"
21
+ desc "Reset the database and run `bin/rails test`"
27
22
  task :db do
28
23
  success = system({ "RAILS_ENV" => ENV.fetch("RAILS_ENV", "test") }, "rake", "db:test:prepare", "test")
29
24
  success || exit(false)
30
25
  end
31
26
 
32
- ["models", "helpers", "channels", "controllers", "mailers", "integration", "jobs", "mailboxes"].each do |name|
33
- task name => "test:prepare" do
34
- Rails::TestUnit::Runner.rake_run(["test/#{name}"])
27
+ [
28
+ *Rails::TestUnit::Runner::TEST_FOLDERS,
29
+ :all,
30
+ :generators,
31
+ :units,
32
+ :functionals,
33
+ :system,
34
+ ].each do |name|
35
+ task name do
36
+ Rails::TestUnit::Runner.run_from_rake("test:#{name}")
35
37
  end
36
38
  end
37
-
38
- desc "Runs all tests, including system tests"
39
- task all: "test:prepare" do
40
- Rails::TestUnit::Runner.rake_run(["test/**/*_test.rb"])
41
- end
42
-
43
- task generators: "test:prepare" do
44
- Rails::TestUnit::Runner.rake_run(["test/lib/generators"])
45
- end
46
-
47
- task units: "test:prepare" do
48
- Rails::TestUnit::Runner.rake_run(["test/models", "test/helpers", "test/unit"])
49
- end
50
-
51
- task functionals: "test:prepare" do
52
- Rails::TestUnit::Runner.rake_run(["test/controllers", "test/mailers", "test/functional"])
53
- end
54
-
55
- desc "Run system tests only"
56
- task system: "test:prepare" do
57
- Rails::TestUnit::Runner.rake_run(["test/system"])
58
- end
59
39
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(ActiveRecord::Base)
4
+ begin
5
+ ActiveRecord::Migration.maintain_test_schema!
6
+ rescue ActiveRecord::PendingMigrationError => e
7
+ puts e.to_s.strip
8
+ exit 1
9
+ end
10
+
11
+ if Rails.configuration.eager_load
12
+ ActiveRecord::Base.descendants.each do |model|
13
+ model.load_schema if !model.abstract_class? && model.table_exists?
14
+ end
15
+ end
16
+ end
data/lib/rails/version.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require_relative "gem_version"
4
4
 
5
5
  module Rails
6
- # Returns the currently loaded version of Rails as a string.
6
+ # Returns the currently loaded version of \Rails as a string.
7
7
  def self.version
8
8
  VERSION::STRING
9
9
  end