railties 7.2.3 → 8.0.5

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +168 -256
  3. data/lib/minitest/rails_plugin.rb +8 -1
  4. data/lib/rails/application/bootstrap.rb +0 -1
  5. data/lib/rails/application/configuration.rb +17 -14
  6. data/lib/rails/application/default_middleware_stack.rb +4 -0
  7. data/lib/rails/application/finisher.rb +2 -3
  8. data/lib/rails/application/routes_reloader.rb +17 -3
  9. data/lib/rails/application.rb +10 -1
  10. data/lib/rails/application_controller.rb +2 -0
  11. data/lib/rails/backtrace_cleaner.rb +2 -2
  12. data/lib/rails/code_statistics.rb +128 -86
  13. data/lib/rails/code_statistics_calculator.rb +78 -76
  14. data/lib/rails/command/helpers/editor.rb +1 -1
  15. data/lib/rails/command.rb +0 -6
  16. data/lib/rails/commands/app/update_command.rb +5 -9
  17. data/lib/rails/commands/console/irb_console.rb +3 -6
  18. data/lib/rails/commands/credentials/USAGE +4 -4
  19. data/lib/rails/commands/credentials/credentials_command.rb +5 -1
  20. data/lib/rails/commands/dev/dev_command.rb +1 -1
  21. data/lib/rails/commands/devcontainer/devcontainer_command.rb +2 -1
  22. data/lib/rails/commands/stats/stats_command.rb +19 -0
  23. data/lib/rails/console/methods.rb +5 -21
  24. data/lib/rails/dev_caching.rb +2 -2
  25. data/lib/rails/engine/configuration.rb +3 -1
  26. data/lib/rails/engine/lazy_route_set.rb +111 -0
  27. data/lib/rails/engine.rb +10 -6
  28. data/lib/rails/gem_version.rb +3 -3
  29. data/lib/rails/generators/actions.rb +3 -3
  30. data/lib/rails/generators/app_base.rb +76 -56
  31. data/lib/rails/generators/base.rb +0 -4
  32. data/lib/rails/generators/bundle_helper.rb +34 -0
  33. data/lib/rails/generators/database.rb +101 -67
  34. data/lib/rails/generators/erb/authentication/authentication_generator.rb +15 -0
  35. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/edit.html.erb +9 -0
  36. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/new.html.erb +8 -0
  37. data/lib/rails/generators/erb/authentication/templates/app/views/sessions/new.html.erb +11 -0
  38. data/lib/rails/generators/generated_attribute.rb +16 -11
  39. data/lib/rails/generators/rails/app/app_generator.rb +30 -30
  40. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +23 -6
  41. data/lib/rails/generators/rails/app/templates/Gemfile.tt +27 -12
  42. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +6 -11
  43. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +10 -3
  44. data/lib/rails/generators/rails/app/templates/bin/dev.tt +1 -0
  45. data/lib/rails/generators/rails/app/templates/bin/setup.tt +5 -8
  46. data/lib/rails/generators/rails/app/templates/bin/thrust.tt +4 -0
  47. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +24 -1
  48. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +23 -0
  49. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +50 -0
  50. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +30 -5
  51. data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +128 -0
  52. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +12 -23
  53. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +31 -51
  54. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +5 -19
  55. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +0 -7
  56. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  57. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +30 -0
  58. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +11 -2
  59. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +3 -3
  60. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +4 -3
  61. data/lib/rails/generators/rails/app/templates/dockerignore.tt +7 -2
  62. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +12 -6
  63. data/lib/rails/generators/rails/app/templates/gitignore.tt +1 -2
  64. data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +17 -0
  65. data/lib/rails/generators/rails/app/templates/public/400.html +114 -0
  66. data/lib/rails/generators/rails/app/templates/public/404.html +113 -66
  67. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +113 -65
  68. data/lib/rails/generators/rails/app/templates/public/422.html +113 -66
  69. data/lib/rails/generators/rails/app/templates/public/500.html +113 -65
  70. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  71. data/lib/rails/generators/rails/app/templates/public/icon.svg +2 -2
  72. data/lib/rails/generators/rails/app/templates/ruby-version.tt +1 -1
  73. data/lib/rails/generators/rails/authentication/USAGE +6 -0
  74. data/lib/rails/generators/rails/authentication/authentication_generator.rb +60 -0
  75. data/lib/rails/generators/rails/authentication/templates/app/channels/application_cable/connection.rb.tt +16 -0
  76. data/lib/rails/generators/rails/authentication/templates/app/controllers/concerns/authentication.rb.tt +52 -0
  77. data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +33 -0
  78. data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +21 -0
  79. data/lib/rails/generators/rails/authentication/templates/app/mailers/passwords_mailer.rb.tt +6 -0
  80. data/lib/rails/generators/rails/authentication/templates/app/models/current.rb.tt +4 -0
  81. data/lib/rails/generators/rails/authentication/templates/app/models/session.rb.tt +3 -0
  82. data/lib/rails/generators/rails/authentication/templates/app/models/user.rb.tt +6 -0
  83. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +4 -0
  84. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +2 -0
  85. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +4 -0
  86. data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
  87. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +12 -2
  88. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +1 -1
  89. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +5 -5
  90. data/lib/rails/generators/rails/plugin/plugin_generator.rb +7 -9
  91. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +1 -1
  92. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +3 -3
  93. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
  94. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +3 -3
  95. data/lib/rails/generators/rails/script/USAGE +18 -0
  96. data/lib/rails/generators/rails/script/script_generator.rb +18 -0
  97. data/lib/rails/generators/rails/script/templates/script.rb.tt +3 -0
  98. data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +18 -0
  99. data/lib/rails/generators/test_unit/authentication/templates/test/fixtures/users.yml.tt +9 -0
  100. data/lib/rails/generators/test_unit/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt +7 -0
  101. data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +7 -0
  102. data/lib/rails/generators.rb +1 -0
  103. data/lib/rails/health_controller.rb +2 -0
  104. data/lib/rails/info.rb +2 -1
  105. data/lib/rails/info_controller.rb +10 -4
  106. data/lib/rails/rack/silence_request.rb +33 -0
  107. data/lib/rails/rack.rb +1 -0
  108. data/lib/rails/source_annotation_extractor.rb +37 -16
  109. data/lib/rails/tasks/statistics.rake +13 -28
  110. data/lib/rails/templates/rails/info/notes.html.erb +65 -0
  111. data/lib/rails/templates/rails/mailers/email.html.erb +1 -1
  112. data/lib/rails/test_unit/line_filtering.rb +24 -3
  113. data/lib/rails/test_unit/reporter.rb +8 -4
  114. data/lib/rails/test_unit/runner.rb +1 -0
  115. metadata +46 -37
  116. data/lib/rails/console/app.rb +0 -8
  117. data/lib/rails/console/helpers.rb +0 -8
  118. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -2
  119. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt +0 -4
  120. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt +0 -4
  121. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +0 -70
  122. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +0 -13
  123. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +0 -13
  124. data/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt +0 -10
  125. data/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt +0 -6
  126. data/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt +0 -17
@@ -1,66 +1,114 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>We're sorry, but something went wrong (500)</title>
5
- <meta name="viewport" content="width=device-width,initial-scale=1">
6
- <style>
7
- .rails-default-error-page {
8
- background-color: #EFEFEF;
9
- color: #2E2F30;
10
- text-align: center;
11
- font-family: arial, sans-serif;
12
- margin: 0;
13
- }
14
-
15
- .rails-default-error-page div.dialog {
16
- width: 95%;
17
- max-width: 33em;
18
- margin: 4em auto 0;
19
- }
20
-
21
- .rails-default-error-page div.dialog > div {
22
- border: 1px solid #CCC;
23
- border-right-color: #999;
24
- border-left-color: #999;
25
- border-bottom-color: #BBB;
26
- border-top: #B00100 solid 4px;
27
- border-top-left-radius: 9px;
28
- border-top-right-radius: 9px;
29
- background-color: white;
30
- padding: 7px 12% 0;
31
- box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
- }
33
-
34
- .rails-default-error-page h1 {
35
- font-size: 100%;
36
- color: #730E15;
37
- line-height: 1.5em;
38
- }
39
-
40
- .rails-default-error-page div.dialog > p {
41
- margin: 0 0 1em;
42
- padding: 1em;
43
- background-color: #F7F7F7;
44
- border: 1px solid #CCC;
45
- border-right-color: #999;
46
- border-left-color: #999;
47
- border-bottom-color: #999;
48
- border-bottom-left-radius: 4px;
49
- border-bottom-right-radius: 4px;
50
- border-top-color: #DADADA;
51
- color: #666;
52
- box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
- }
54
- </style>
55
- </head>
56
-
57
- <body class="rails-default-error-page">
58
- <!-- This file lives in public/500.html -->
59
- <div class="dialog">
60
- <div>
61
- <h1>We're sorry, but something went wrong.</h1>
62
- </div>
63
- <p>If you are the application owner check the logs for more information.</p>
64
- </div>
65
- </body>
1
+ <!doctype html>
2
+
3
+ <html lang="en">
4
+
5
+ <head>
6
+
7
+ <title>We’re sorry, but something went wrong (500 Internal Server Error)</title>
8
+
9
+ <meta charset="utf-8">
10
+ <meta name="viewport" content="initial-scale=1, width=device-width">
11
+ <meta name="robots" content="noindex, nofollow">
12
+
13
+ <style>
14
+
15
+ *, *::before, *::after {
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ * {
20
+ margin: 0;
21
+ }
22
+
23
+ html {
24
+ font-size: 16px;
25
+ }
26
+
27
+ body {
28
+ background: #FFF;
29
+ color: #261B23;
30
+ display: grid;
31
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Aptos, Roboto, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
32
+ font-size: clamp(1rem, 2.5vw, 2rem);
33
+ -webkit-font-smoothing: antialiased;
34
+ font-style: normal;
35
+ font-weight: 400;
36
+ letter-spacing: -0.0025em;
37
+ line-height: 1.4;
38
+ min-height: 100vh;
39
+ place-items: center;
40
+ text-rendering: optimizeLegibility;
41
+ -webkit-text-size-adjust: 100%;
42
+ }
43
+
44
+ a {
45
+ color: inherit;
46
+ font-weight: 700;
47
+ text-decoration: underline;
48
+ text-underline-offset: 0.0925em;
49
+ }
50
+
51
+ b, strong {
52
+ font-weight: 700;
53
+ }
54
+
55
+ i, em {
56
+ font-style: italic;
57
+ }
58
+
59
+ main {
60
+ display: grid;
61
+ gap: 1em;
62
+ padding: 2em;
63
+ place-items: center;
64
+ text-align: center;
65
+ }
66
+
67
+ main header {
68
+ width: min(100%, 12em);
69
+ }
70
+
71
+ main header svg {
72
+ height: auto;
73
+ max-width: 100%;
74
+ width: 100%;
75
+ }
76
+
77
+ main article {
78
+ width: min(100%, 30em);
79
+ }
80
+
81
+ main article p {
82
+ font-size: 75%;
83
+ }
84
+
85
+ main article br {
86
+
87
+ display: none;
88
+
89
+ @media(min-width: 48em) {
90
+ display: inline;
91
+ }
92
+
93
+ }
94
+
95
+ </style>
96
+
97
+ </head>
98
+
99
+ <body>
100
+
101
+ <!-- This file lives in public/500.html -->
102
+
103
+ <main>
104
+ <header>
105
+ <svg height="172" viewBox="0 0 480 172" width="480" xmlns="http://www.w3.org/2000/svg"><path d="m101.23 93.8427c-8.1103 0-15.4098 3.7849-19.7354 8.3813h-36.2269v-99.21891h103.8143v37.03791h-68.3984v24.8722c5.1366-2.7035 15.1396-5.9477 24.6014-5.9477 35.146 0 56.233 22.7094 56.233 55.4215 0 34.605-23.791 57.315-60.558 57.315-37.8492 0-61.64-22.169-63.8028-55.963h42.9857c1.0814 10.814 9.1919 19.195 21.6281 19.195 11.355 0 19.465-8.381 19.465-20.547 0-11.625-7.299-20.5463-20.006-20.5463zm138.833 77.8613c-40.822 0-64.884-35.146-64.884-85.7015 0-50.5554 24.062-85.700907 64.884-85.700907 40.823 0 64.884 35.145507 64.884 85.700907 0 50.5555-24.061 85.7015-64.884 85.7015zm0-133.2831c-17.572 0-22.709 21.8984-22.709 47.5816 0 25.6835 5.137 47.5815 22.709 47.5815 17.303 0 22.71-21.898 22.71-47.5815 0-25.6832-5.407-47.5816-22.71-47.5816zm140.456 133.2831c-40.823 0-64.884-35.146-64.884-85.7015 0-50.5554 24.061-85.700907 64.884-85.700907 40.822 0 64.884 35.145507 64.884 85.700907 0 50.5555-24.062 85.7015-64.884 85.7015zm0-133.2831c-17.573 0-22.71 21.8984-22.71 47.5816 0 25.6835 5.137 47.5815 22.71 47.5815 17.302 0 22.709-21.898 22.709-47.5815 0-25.6832-5.407-47.5816-22.709-47.5816z" fill="#f0eff0"/><path d="m23.1377 68.9967v34.0033h-8.9162v-34.0033zm4.3157 34.0033v-24.921h8.6947v2.1598c1.3845-1.5506 3.8212-2.7136 6.701-2.7136 5.538 0 8.8054 3.5997 8.8054 9.1377v16.3371h-8.6393v-14.2327c0-2.049-1.0522-3.5443-3.2674-3.5443-1.7168 0-3.1567.9969-3.5997 2.7136v15.0634zm29.9913-8.5839v-9.5807h-3.655v-6.7564h3.655v-6.8671h8.5839v6.8671h5.2058v6.7564h-5.2058v8.307c0 1.9383.9415 2.769 2.6583 2.769.9414 0 1.9937-.2216 2.769-.5538v7.3654c-.9969.443-2.8798.775-4.8181.775-5.8703 0-9.1931-2.769-9.1931-9.0819zm32.3666-.1108h8.0301c-.8861 5.7597-5.2057 9.2487-11.6852 9.2487-7.6424 0-12.682-5.2613-12.682-13.0145 0-7.6978 5.3165-13.0143 12.5159-13.0143 7.6424 0 11.9621 5.095 11.9621 12.5159v2.1598h-16.1156c.2769 2.9905 1.8275 4.5965 4.3196 4.5965 1.7722 0 3.1567-.7753 3.6551-2.4921zm-3.8212-10.0237c-2.0491 0-3.4336 1.2737-3.9874 3.5997h7.5317c-.1107-2.0491-1.3845-3.5997-3.5443-3.5997zm31.4299-6.3134v8.3624c-1.052-.5538-2.215-.7753-3.599-.7753-2.382 0-3.988 1.0522-4.431 2.8244v14.6203h-8.694v-24.921h8.694v2.2152c1.219-1.6614 3.157-2.769 5.649-2.769 1.108 0 1.994.2215 2.381.443zm2.949 25.0318v-24.921h8.694v2.1598c1.385-1.5506 3.821-2.7136 6.701-2.7136 5.538 0 8.806 3.5997 8.806 9.1377v16.3371h-8.64v-14.2327c0-2.049-1.052-3.5443-3.267-3.5443-1.717 0-3.157.9969-3.6 2.7136v15.0634zm50.371 0h-8.363v-1.274c-.83.831-3.323 1.717-5.981 1.717-4.929 0-9.082-2.769-9.082-8.0301 0-4.818 4.153-7.9193 9.581-7.9193 2.049 0 4.485.6646 5.482 1.3845v-1.606c0-1.606-.941-2.9905-3.046-2.9905-1.606 0-2.547.7199-2.935 1.8275h-8.196c.72-4.8181 4.984-8.6393 11.408-8.6393 7.089 0 11.132 3.7659 11.132 10.2453zm-8.363-6.9779v-1.4399c-.554-1.0522-2.049-1.7167-3.655-1.7167-1.717 0-3.433.7199-3.433 2.3813 0 1.7168 1.716 2.4367 3.433 2.4367 1.606 0 3.101-.6645 3.655-1.6614zm20.742-29.0191v35.997h-8.694v-35.997zm13.036 25.9178h9.248c.72 2.326 2.714 3.489 5.483 3.489 2.713 0 4.596-1.163 4.596-3.2674 0-1.6061-1.052-2.326-3.212-2.8244l-6.534-1.3845c-4.985-1.1076-8.751-3.7105-8.751-9.47 0-6.6456 5.538-11.0206 13.07-11.0206 8.307 0 13.014 4.5411 13.956 10.4114h-8.695c-.72-1.8829-2.27-3.3228-5.205-3.3228-2.548 0-4.265 1.1076-4.265 2.9905 0 1.4953 1.052 2.326 2.825 2.7137l6.645 1.5506c5.815 1.3845 9.027 4.5412 9.027 9.8023 0 6.9778-5.87 10.9654-13.291 10.9654-8.141 0-13.679-3.9322-14.897-10.6332zm46.509 1.3845h8.031c-.887 5.7597-5.206 9.2487-11.686 9.2487-7.642 0-12.682-5.2613-12.682-13.0145 0-7.6978 5.317-13.0143 12.516-13.0143 7.643 0 11.962 5.095 11.962 12.5159v2.1598h-16.115c.277 2.9905 1.827 4.5965 4.319 4.5965 1.773 0 3.157-.7753 3.655-2.4921zm-3.821-10.0237c-2.049 0-3.433 1.2737-3.987 3.5997h7.532c-.111-2.0491-1.385-3.5997-3.545-3.5997zm31.431-6.3134v8.3624c-1.053-.5538-2.216-.7753-3.6-.7753-2.381 0-3.988 1.0522-4.431 2.8244v14.6203h-8.694v-24.921h8.694v2.2152c1.219-1.6614 3.157-2.769 5.649-2.769 1.108 0 1.994.2215 2.382.443zm18.288 25.0318h-7.809l-9.47-24.921h8.861l4.763 14.288 4.652-14.288h8.528zm25.614-8.6947h8.03c-.886 5.7597-5.206 9.2487-11.685 9.2487-7.642 0-12.682-5.2613-12.682-13.0145 0-7.6978 5.316-13.0143 12.516-13.0143 7.642 0 11.962 5.095 11.962 12.5159v2.1598h-16.116c.277 2.9905 1.828 4.5965 4.32 4.5965 1.772 0 3.157-.7753 3.655-2.4921zm-3.821-10.0237c-2.049 0-3.434 1.2737-3.988 3.5997h7.532c-.111-2.0491-1.384-3.5997-3.544-3.5997zm31.43-6.3134v8.3624c-1.052-.5538-2.215-.7753-3.6-.7753-2.381 0-3.987 1.0522-4.43 2.8244v14.6203h-8.695v-24.921h8.695v2.2152c1.218-1.6614 3.157-2.769 5.649-2.769 1.107 0 1.993.2215 2.381.443zm13.703-8.9715h24.312v7.6424h-15.562v5.3165h14.232v7.4763h-14.232v5.8703h15.562v7.6978h-24.312zm44.667 8.9715v8.3624c-1.052-.5538-2.215-.7753-3.6-.7753-2.381 0-3.987 1.0522-4.43 2.8244v14.6203h-8.695v-24.921h8.695v2.2152c1.218-1.6614 3.156-2.769 5.648-2.769 1.108 0 1.994.2215 2.382.443zm19.673 0v8.3624c-1.053-.5538-2.216-.7753-3.6-.7753-2.381 0-3.987 1.0522-4.43 2.8244v14.6203h-8.695v-24.921h8.695v2.2152c1.218-1.6614 3.156-2.769 5.648-2.769 1.108 0 1.994.2215 2.382.443zm26.769 12.5713c0 7.6978-5.15 13.0145-12.737 13.0145-7.532 0-12.738-5.3167-12.738-13.0145s5.206-13.0143 12.738-13.0143c7.587 0 12.737 5.3165 12.737 13.0143zm-8.529 0c0-3.4336-1.495-5.8703-4.208-5.8703-2.659 0-4.154 2.4367-4.154 5.8703s1.495 5.8149 4.154 5.8149c2.713 0 4.208-2.3813 4.208-5.8149zm28.082-12.5713v8.3624c-1.052-.5538-2.215-.7753-3.6-.7753-2.381 0-3.987 1.0522-4.43 2.8244v14.6203h-8.695v-24.921h8.695v2.2152c1.218-1.6614 3.157-2.769 5.649-2.769 1.107 0 1.993.2215 2.381.443z" fill="#d30001"/></svg>
106
+ </header>
107
+ <article>
108
+ <p><strong>We’re sorry, but something went wrong.</strong><br> If you’re the application owner check the logs for more information.</p>
109
+ </article>
110
+ </main>
111
+
112
+ </body>
113
+
66
114
  </html>
@@ -1,3 +1,3 @@
1
- <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
2
- <rect width="100%" height="100%" fill="red"/>
1
+ <svg width="512" height="512" xmlns="http://www.w3.org/2000/svg">
2
+ <circle cx="256" cy="256" r="256" fill="red"/>
3
3
  </svg>
@@ -1 +1 @@
1
- <%= ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}" %>
1
+ <%= version_manager_ruby_version %>
@@ -0,0 +1,6 @@
1
+ Description:
2
+ Generates a basic authentication system with users, sessions, and password reset.
3
+
4
+ Example:
5
+ `bin/rails generate authentication`
6
+
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/bundle_helper"
4
+
5
+ module Rails
6
+ module Generators
7
+ class AuthenticationGenerator < Base # :nodoc:
8
+ include BundleHelper
9
+
10
+ class_option :api, type: :boolean,
11
+ desc: "Generate API-only controllers and models, with no view templates"
12
+
13
+ hook_for :template_engine, as: :authentication do |template_engine|
14
+ invoke template_engine unless options.api?
15
+ end
16
+
17
+ def create_authentication_files
18
+ template "app/models/session.rb"
19
+ template "app/models/user.rb"
20
+ template "app/models/current.rb"
21
+
22
+ template "app/controllers/sessions_controller.rb"
23
+ template "app/controllers/concerns/authentication.rb"
24
+ template "app/controllers/passwords_controller.rb"
25
+
26
+ template "app/channels/application_cable/connection.rb" if defined?(ActionCable::Engine)
27
+
28
+ template "app/mailers/passwords_mailer.rb"
29
+
30
+ template "app/views/passwords_mailer/reset.html.erb"
31
+ template "app/views/passwords_mailer/reset.text.erb"
32
+ end
33
+
34
+ def configure_application_controller
35
+ inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " include Authentication\n"
36
+ end
37
+
38
+ def configure_authentication_routes
39
+ route "resources :passwords, param: :token"
40
+ route "resource :session"
41
+ end
42
+
43
+ def enable_bcrypt
44
+ if File.read("Gemfile").include?('gem "bcrypt"')
45
+ uncomment_lines "Gemfile", /gem "bcrypt"/
46
+ bundle_command("install --quiet")
47
+ else
48
+ bundle_command("add bcrypt", {}, quiet: true)
49
+ end
50
+ end
51
+
52
+ def add_migrations
53
+ generate "migration CreateUsers email_address:string!:uniq password_digest:string! --force"
54
+ generate "migration CreateSessions user:references ip_address:string user_agent:string --force"
55
+ end
56
+
57
+ hook_for :test_framework
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,16 @@
1
+ module ApplicationCable
2
+ class Connection < ActionCable::Connection::Base
3
+ identified_by :current_user
4
+
5
+ def connect
6
+ set_current_user || reject_unauthorized_connection
7
+ end
8
+
9
+ private
10
+ def set_current_user
11
+ if session = Session.find_by(id: cookies.signed[:session_id])
12
+ self.current_user = session.user
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,52 @@
1
+ module Authentication
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ before_action :require_authentication
6
+ helper_method :authenticated?
7
+ end
8
+
9
+ class_methods do
10
+ def allow_unauthenticated_access(**options)
11
+ skip_before_action :require_authentication, **options
12
+ end
13
+ end
14
+
15
+ private
16
+ def authenticated?
17
+ resume_session
18
+ end
19
+
20
+ def require_authentication
21
+ resume_session || request_authentication
22
+ end
23
+
24
+ def resume_session
25
+ Current.session ||= find_session_by_cookie
26
+ end
27
+
28
+ def find_session_by_cookie
29
+ Session.find_by(id: cookies.signed[:session_id]) if cookies.signed[:session_id]
30
+ end
31
+
32
+ def request_authentication
33
+ session[:return_to_after_authenticating] = request.url
34
+ redirect_to new_session_path
35
+ end
36
+
37
+ def after_authentication_url
38
+ session.delete(:return_to_after_authenticating) || root_url
39
+ end
40
+
41
+ def start_new_session_for(user)
42
+ user.sessions.create!(user_agent: request.user_agent, ip_address: request.remote_ip).tap do |session|
43
+ Current.session = session
44
+ cookies.signed.permanent[:session_id] = { value: session.id, httponly: true, same_site: :lax }
45
+ end
46
+ end
47
+
48
+ def terminate_session
49
+ Current.session.destroy
50
+ cookies.delete(:session_id)
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ class PasswordsController < ApplicationController
2
+ allow_unauthenticated_access
3
+ before_action :set_user_by_token, only: %i[ edit update ]
4
+
5
+ def new
6
+ end
7
+
8
+ def create
9
+ if user = User.find_by(email_address: params[:email_address])
10
+ PasswordsMailer.reset(user).deliver_later
11
+ end
12
+
13
+ redirect_to new_session_path, notice: "Password reset instructions sent (if user with that email address exists)."
14
+ end
15
+
16
+ def edit
17
+ end
18
+
19
+ def update
20
+ if @user.update(params.permit(:password, :password_confirmation))
21
+ redirect_to new_session_path, notice: "Password has been reset."
22
+ else
23
+ redirect_to edit_password_path(params[:token]), alert: "Passwords did not match."
24
+ end
25
+ end
26
+
27
+ private
28
+ def set_user_by_token
29
+ @user = User.find_by_password_reset_token!(params[:token])
30
+ rescue ActiveSupport::MessageVerifier::InvalidSignature
31
+ redirect_to new_password_path, alert: "Password reset link is invalid or has expired."
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ class SessionsController < ApplicationController
2
+ allow_unauthenticated_access only: %i[ new create ]
3
+ rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_url, alert: "Try again later." }
4
+
5
+ def new
6
+ end
7
+
8
+ def create
9
+ if user = User.authenticate_by(params.permit(:email_address, :password))
10
+ start_new_session_for user
11
+ redirect_to after_authentication_url
12
+ else
13
+ redirect_to new_session_path, alert: "Try another email address or password."
14
+ end
15
+ end
16
+
17
+ def destroy
18
+ terminate_session
19
+ redirect_to new_session_path
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ class PasswordsMailer < ApplicationMailer
2
+ def reset(user)
3
+ @user = user
4
+ mail subject: "Reset your password", to: user.email_address
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ class Current < ActiveSupport::CurrentAttributes
2
+ attribute :session
3
+ delegate :user, to: :session, allow_nil: true
4
+ end
@@ -0,0 +1,3 @@
1
+ class Session < ApplicationRecord
2
+ belongs_to :user
3
+ end
@@ -0,0 +1,6 @@
1
+ class User < ApplicationRecord
2
+ has_secure_password
3
+ has_many :sessions, dependent: :destroy
4
+
5
+ normalizes :email_address, with: ->(e) { e.strip.downcase }
6
+ end
@@ -0,0 +1,4 @@
1
+ <p>
2
+ You can reset your password within the next 15 minutes on
3
+ <%%= link_to "this password reset page", edit_password_url(@user.password_reset_token) %>.
4
+ </p>
@@ -0,0 +1,2 @@
1
+ You can reset your password within the next 15 minutes on this password reset page:
2
+ <%%= edit_password_url(@user.password_reset_token) %>
@@ -1,3 +1,7 @@
1
+ # smtp:
2
+ # user_name: my-smtp-user
3
+ # password: my-smtp-password
4
+ #
1
5
  # aws:
2
6
  # access_key_id: 123
3
7
  # secret_access_key: 345
@@ -35,7 +35,7 @@ module Rails
35
35
  end
36
36
 
37
37
  def edit_database_config
38
- template("config/databases/#{options[:database]}.yml", "config/database.yml")
38
+ template(database.template, "config/database.yml")
39
39
  end
40
40
 
41
41
  def edit_gemfile
@@ -26,6 +26,12 @@ module Rails
26
26
  class_option :dev, type: :boolean, default: false,
27
27
  desc: "For applications pointing to a local Rails checkout"
28
28
 
29
+ class_option :kamal, type: :boolean, default: true,
30
+ desc: "Include configuration for Kamal"
31
+
32
+ class_option :skip_solid, type: :boolean, default: nil,
33
+ desc: "Skip Solid Cache, Queue, and Cable setup"
34
+
29
35
  source_paths << File.expand_path(File.join(base_name, "app", "templates"), base_root)
30
36
 
31
37
  def create_devcontainer
@@ -38,9 +44,11 @@ module Rails
38
44
 
39
45
  def update_application_system_test_case
40
46
  return unless options[:system_test]
41
- return unless File.exist?("test/application_system_test_case.rb")
42
47
 
43
- gsub_file("test/application_system_test_case.rb", /^\s*driven_by\b.*/, system_test_configuration)
48
+ system_test_case_path = File.expand_path "test/application_system_test_case.rb", destination_root
49
+ return unless File.exist? system_test_case_path
50
+
51
+ gsub_file(system_test_case_path, /^\s*driven_by\b.*/, system_test_configuration)
44
52
  end
45
53
 
46
54
  def update_database_yml
@@ -78,6 +86,7 @@ module Rails
78
86
  @container_env["CAPYBARA_SERVER_PORT"] = "45678" if options[:system_test]
79
87
  @container_env["SELENIUM_HOST"] = "selenium" if options[:system_test]
80
88
  @container_env["REDIS_URL"] = "redis://redis:6379/1" if options[:redis]
89
+ @container_env["KAMAL_REGISTRY_PASSWORD"] = "$KAMAL_REGISTRY_PASSWORD" if options[:kamal]
81
90
  @container_env["DB_HOST"] = database.name if database.service
82
91
 
83
92
  @container_env
@@ -103,6 +112,7 @@ module Rails
103
112
 
104
113
  @features["ghcr.io/rails/devcontainer/features/activestorage"] = {} if options[:active_storage]
105
114
  @features["ghcr.io/devcontainers/features/node:1"] = {} if options[:node]
115
+ @features["ghcr.io/devcontainers/features/docker-outside-of-docker:1"] = { moby: false } if options[:kamal]
106
116
 
107
117
  @features.merge!(database.feature) if database.feature
108
118
 
@@ -1,3 +1,3 @@
1
1
  # Make sure RUBY_VERSION matches the Ruby version in .ruby-version
2
- ARG RUBY_VERSION=<%= gem_ruby_version %>
2
+ ARG RUBY_VERSION=<%= Gem.ruby_version %>
3
3
  FROM ghcr.io/rails/devcontainer/images/ruby:$RUBY_VERSION
@@ -1,5 +1,5 @@
1
- // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2
- // README at: https://github.com/devcontainers/templates/tree/main/src/ruby
1
+ // For format details, see https://containers.dev/implementors/json_reference/.
2
+ // For config options, see the README at: https://github.com/devcontainers/templates/tree/main/src/ruby
3
3
  {
4
4
  "name": "<%= options[:app_name] %>",
5
5
  "dockerComposeFile": "compose.yaml",
@@ -8,7 +8,7 @@
8
8
 
9
9
  // Features to add to the dev container. More info: https://containers.dev/features.
10
10
  "features": {
11
- <%= features.map { |key, value| "\"#{key}\": #{value.as_json}" }.join(",\n ") %>
11
+ <%= features.map { |key, value| "\"#{key}\": #{value.to_json}" }.join(",\n ") %>
12
12
  },
13
13
 
14
14
  <%- if !container_env.empty? -%>
@@ -23,7 +23,7 @@
23
23
  // Configure tool-specific properties.
24
24
  // "customizations": {},
25
25
 
26
- // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
26
+ // Uncomment to connect as root instead. More info: https://containers.dev/implementors/json_reference/#remoteUser.
27
27
  // "remoteUser": "root",
28
28
 
29
29
  <%- if !mounts.empty? -%>
@@ -33,5 +33,5 @@
33
33
  <%- end -%>
34
34
 
35
35
  // Use 'postCreateCommand' to run commands after the container is created.
36
- "postCreateCommand": "bin/setup"
36
+ "postCreateCommand": "bin/setup --skip-server"
37
37
  }
@@ -122,9 +122,12 @@ module Rails
122
122
  def generate_test_dummy(force = false)
123
123
  opts = options.transform_keys(&:to_sym).except(*DUMMY_IGNORE_OPTIONS)
124
124
  opts[:force] = force
125
+ opts[:skip_thruster] = true
125
126
  opts[:skip_brakeman] = true
126
127
  opts[:skip_bundle] = true
127
128
  opts[:skip_ci] = true
129
+ opts[:skip_kamal] = true
130
+ opts[:skip_solid] = true
128
131
  opts[:skip_git] = true
129
132
  opts[:skip_hotwire] = true
130
133
  opts[:skip_rubocop] = true
@@ -149,9 +152,8 @@ module Rails
149
152
  end
150
153
  end
151
154
 
152
- def test_dummy_sprocket_assets
153
- template "rails/stylesheets.css", "#{dummy_path}/app/assets/stylesheets/application.css", force: true
154
- template "rails/dummy_manifest.js", "#{dummy_path}/app/assets/config/manifest.js", force: true
155
+ def test_dummy_assets
156
+ template "rails/stylesheets.css", "#{dummy_path}/app/assets/stylesheets/application.css", force: true
155
157
  end
156
158
 
157
159
  def test_dummy_clean
@@ -159,7 +161,7 @@ module Rails
159
161
  remove_file ".ruby-version"
160
162
  remove_dir "db"
161
163
  remove_file "Gemfile"
162
- remove_file "lib/tasks"
164
+ remove_dir "lib"
163
165
  remove_file "public/robots.txt"
164
166
  remove_file "README.md"
165
167
  remove_file "test"
@@ -167,10 +169,6 @@ module Rails
167
169
  end
168
170
  end
169
171
 
170
- def assets_manifest
171
- template "rails/engine_manifest.js", "app/assets/config/#{underscored_name}_manifest.js"
172
- end
173
-
174
172
  def stylesheets
175
173
  if mountable?
176
174
  copy_file "rails/stylesheets.css",
@@ -361,7 +359,7 @@ module Rails
361
359
  mute do
362
360
  build(:generate_test_dummy)
363
361
  build(:test_dummy_config)
364
- build(:test_dummy_sprocket_assets) unless skip_sprockets?
362
+ build(:test_dummy_assets) unless skip_asset_pipeline?
365
363
  build(:test_dummy_clean)
366
364
  # ensure that bin/rails has proper dummy_path
367
365
  build(:bin)
@@ -19,5 +19,5 @@ gem "rubocop-rails-omakase", require: false
19
19
  <% end -%>
20
20
  <% if RUBY_PLATFORM.match?(/mingw|mswin|java/) -%>
21
21
 
22
- gem "tzinfo-data", platforms: %i[ <%= bundler_windows_platforms %> jruby ]
22
+ gem "tzinfo-data", platforms: %i[ windows jruby ]
23
23
  <% end -%>
@@ -11,7 +11,7 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
13
  - name: Checkout code
14
- uses: actions/checkout@v4
14
+ uses: actions/checkout@v6
15
15
 
16
16
  - name: Set up Ruby
17
17
  uses: ruby/setup-ruby@v1
@@ -64,10 +64,10 @@ jobs:
64
64
  <%- end -%>
65
65
  steps:
66
66
  - name: Install packages
67
- run: sudo apt-get update && sudo apt-get install --no-install-recommends -y google-chrome-stable <%= dockerfile_base_packages.join(" ") %>
67
+ run: sudo apt-get update && sudo apt-get install --no-install-recommends -y <%= ci_packages.join(" ") %>
68
68
 
69
69
  - name: Checkout code
70
- uses: actions/checkout@v4
70
+ uses: actions/checkout@v6
71
71
 
72
72
  - name: Set up Ruby
73
73
  uses: ruby/setup-ruby@v1
@@ -42,7 +42,7 @@ class <%= controller_class_name %>Controller < ApplicationController
42
42
  private
43
43
  # Use callbacks to share common setup or constraints between actions.
44
44
  def set_<%= singular_table_name %>
45
- @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
45
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params.expect(:id)") %>
46
46
  end
47
47
 
48
48
  # Only allow a list of trusted parameters through.
@@ -50,7 +50,7 @@ class <%= controller_class_name %>Controller < ApplicationController
50
50
  <%- if attributes_names.empty? -%>
51
51
  params.fetch(:<%= singular_table_name %>, {})
52
52
  <%- else -%>
53
- params.require(:<%= singular_table_name %>).permit(<%= permitted_params %>)
53
+ params.expect(<%= singular_table_name %>: [ <%= permitted_params %> ])
54
54
  <%- end -%>
55
55
  end
56
56
  end