railties 7.1.3.4 → 8.0.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 (193) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -775
  3. data/lib/minitest/rails_plugin.rb +6 -3
  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 -7
  7. data/lib/rails/application/configuration.rb +81 -43
  8. data/lib/rails/application/default_middleware_stack.rb +4 -0
  9. data/lib/rails/application/dummy_config.rb +2 -2
  10. data/lib/rails/application/finisher.rb +9 -3
  11. data/lib/rails/application/routes_reloader.rb +16 -2
  12. data/lib/rails/application.rb +27 -86
  13. data/lib/rails/backtrace_cleaner.rb +19 -4
  14. data/lib/rails/cli.rb +0 -1
  15. data/lib/rails/code_statistics.rb +128 -86
  16. data/lib/rails/code_statistics_calculator.rb +78 -76
  17. data/lib/rails/command/helpers/editor.rb +1 -1
  18. data/lib/rails/command.rb +0 -6
  19. data/lib/rails/commands/app/update_command.rb +94 -0
  20. data/lib/rails/commands/boot/boot_command.rb +14 -0
  21. data/lib/rails/commands/console/console_command.rb +2 -21
  22. data/lib/rails/commands/console/irb_console.rb +128 -0
  23. data/lib/rails/commands/credentials/USAGE +4 -4
  24. data/lib/rails/commands/credentials/credentials_command.rb +7 -3
  25. data/lib/rails/commands/dbconsole/dbconsole_command.rb +21 -30
  26. data/lib/rails/commands/dev/dev_command.rb +1 -1
  27. data/lib/rails/commands/devcontainer/devcontainer_command.rb +40 -0
  28. data/lib/rails/commands/rake/rake_command.rb +1 -1
  29. data/lib/rails/commands/runner/runner_command.rb +14 -3
  30. data/lib/rails/commands/server/server_command.rb +5 -3
  31. data/lib/rails/commands/stats/stats_command.rb +19 -0
  32. data/lib/rails/commands/test/test_command.rb +2 -0
  33. data/lib/rails/configuration.rb +10 -1
  34. data/lib/rails/console/methods.rb +7 -0
  35. data/lib/rails/dev_caching.rb +2 -2
  36. data/lib/rails/engine/configuration.rb +3 -1
  37. data/lib/rails/engine/lazy_route_set.rb +114 -0
  38. data/lib/rails/engine.rb +16 -12
  39. data/lib/rails/gem_version.rb +4 -4
  40. data/lib/rails/generators/actions.rb +3 -3
  41. data/lib/rails/generators/app_base.rb +115 -68
  42. data/lib/rails/generators/base.rb +1 -1
  43. data/lib/rails/generators/database.rb +263 -71
  44. data/lib/rails/generators/erb/authentication/authentication_generator.rb +15 -0
  45. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/edit.html.erb +9 -0
  46. data/lib/rails/generators/erb/authentication/templates/app/views/passwords/new.html.erb +8 -0
  47. data/lib/rails/generators/erb/authentication/templates/app/views/sessions/new.html.erb +11 -0
  48. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  49. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  50. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  51. data/lib/rails/generators/generated_attribute.rb +42 -12
  52. data/lib/rails/generators/migration.rb +3 -3
  53. data/lib/rails/generators/rails/app/app_generator.rb +75 -54
  54. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +33 -17
  55. data/lib/rails/generators/rails/app/templates/Gemfile.tt +38 -23
  56. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +6 -11
  57. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  58. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +17 -3
  59. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  60. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  61. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  62. data/lib/rails/generators/rails/app/templates/bin/dev.tt +1 -0
  63. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  64. data/lib/rails/generators/rails/app/templates/bin/setup.tt +6 -5
  65. data/lib/rails/generators/rails/app/templates/bin/thrust.tt +4 -0
  66. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +1 -1
  67. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +26 -3
  68. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +30 -0
  69. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +47 -0
  70. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +26 -3
  71. data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +128 -0
  72. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +22 -26
  73. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +36 -48
  74. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +7 -18
  75. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +0 -7
  76. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  77. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +30 -0
  78. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +35 -27
  79. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +6 -0
  80. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +7 -1
  81. data/lib/rails/generators/rails/app/templates/dockerignore.tt +20 -2
  82. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +144 -0
  83. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  84. data/lib/rails/generators/rails/app/templates/gitignore.tt +4 -5
  85. data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +17 -0
  86. data/lib/rails/generators/rails/app/templates/public/400.html +114 -0
  87. data/lib/rails/generators/rails/app/templates/public/404.html +113 -66
  88. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +114 -0
  89. data/lib/rails/generators/rails/app/templates/public/422.html +113 -66
  90. data/lib/rails/generators/rails/app/templates/public/500.html +113 -65
  91. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  92. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  93. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  94. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  95. data/lib/rails/generators/rails/authentication/USAGE +6 -0
  96. data/lib/rails/generators/rails/authentication/authentication_generator.rb +58 -0
  97. data/lib/rails/generators/rails/authentication/templates/app/channels/application_cable/connection.rb.tt +16 -0
  98. data/lib/rails/generators/rails/authentication/templates/app/controllers/concerns/authentication.rb.tt +52 -0
  99. data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +33 -0
  100. data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +21 -0
  101. data/lib/rails/generators/rails/authentication/templates/app/mailers/passwords_mailer.rb.tt +6 -0
  102. data/lib/rails/generators/rails/authentication/templates/app/models/current.rb.tt +4 -0
  103. data/lib/rails/generators/rails/authentication/templates/app/models/session.rb.tt +3 -0
  104. data/lib/rails/generators/rails/authentication/templates/app/models/user.rb.tt +6 -0
  105. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +4 -0
  106. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +2 -0
  107. data/lib/rails/generators/rails/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt +7 -0
  108. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
  109. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +4 -0
  110. data/lib/rails/generators/rails/db/system/change/change_generator.rb +132 -21
  111. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +176 -0
  112. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  113. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  114. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  115. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  116. data/lib/rails/generators/rails/plugin/plugin_generator.rb +47 -16
  117. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  118. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +6 -2
  119. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  120. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  121. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  122. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  123. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  124. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  125. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -2
  126. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
  127. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +3 -3
  128. data/lib/rails/generators/rails/script/USAGE +18 -0
  129. data/lib/rails/generators/rails/script/script_generator.rb +18 -0
  130. data/lib/rails/generators/rails/script/templates/script.rb.tt +3 -0
  131. data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +14 -0
  132. data/lib/rails/generators/test_unit/authentication/templates/test/fixtures/users.yml.tt +9 -0
  133. data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +7 -0
  134. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  135. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  136. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +15 -1
  137. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  138. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  139. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  140. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  141. data/lib/rails/generators/testing/assertions.rb +20 -0
  142. data/lib/rails/generators/testing/behavior.rb +7 -6
  143. data/lib/rails/generators.rb +7 -2
  144. data/lib/rails/health_controller.rb +1 -1
  145. data/lib/rails/info.rb +2 -2
  146. data/lib/rails/info_controller.rb +10 -2
  147. data/lib/rails/mailers_controller.rb +14 -1
  148. data/lib/rails/paths.rb +2 -2
  149. data/lib/rails/pwa_controller.rb +15 -0
  150. data/lib/rails/rack/logger.rb +15 -7
  151. data/lib/rails/rack/silence_request.rb +33 -0
  152. data/lib/rails/rack.rb +1 -0
  153. data/lib/rails/railtie/configurable.rb +2 -2
  154. data/lib/rails/railtie.rb +15 -16
  155. data/lib/rails/source_annotation_extractor.rb +31 -14
  156. data/lib/rails/tasks/framework.rake +0 -26
  157. data/lib/rails/tasks/statistics.rake +13 -28
  158. data/lib/rails/tasks/tmp.rake +1 -1
  159. data/lib/rails/templates/layouts/application.html.erb +1 -1
  160. data/lib/rails/templates/rails/info/notes.html.erb +65 -0
  161. data/lib/rails/templates/rails/mailers/email.html.erb +12 -8
  162. data/lib/rails/templates/rails/welcome/index.html.erb +4 -2
  163. data/lib/rails/test_help.rb +2 -4
  164. data/lib/rails/test_unit/reporter.rb +8 -2
  165. data/lib/rails/test_unit/runner.rb +27 -2
  166. data/lib/rails/test_unit/test_parser.rb +48 -0
  167. data/lib/rails.rb +7 -4
  168. metadata +77 -45
  169. data/lib/rails/app_updater.rb +0 -40
  170. data/lib/rails/commands/secrets/USAGE +0 -61
  171. data/lib/rails/commands/secrets/secrets_command.rb +0 -47
  172. data/lib/rails/console/app.rb +0 -35
  173. data/lib/rails/console/helpers.rb +0 -19
  174. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -2
  175. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt +0 -4
  176. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt +0 -4
  177. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  178. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +0 -54
  179. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  180. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  181. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  182. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  183. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +0 -284
  184. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +0 -13
  185. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  186. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  187. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  188. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +0 -13
  189. data/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt +0 -10
  190. data/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt +0 -6
  191. data/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt +0 -17
  192. data/lib/rails/ruby_version_check.rb +0 -17
  193. data/lib/rails/secrets.rb +0 -110
@@ -0,0 +1,103 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [ main ]
7
+
8
+ jobs:
9
+ <%- unless skip_rubocop? -%>
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: <%= ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}" %>
20
+ bundler-cache: true
21
+
22
+ - name: Lint code for consistent style
23
+ run: bin/rubocop -f github
24
+
25
+ <% end -%>
26
+ <% unless options[:skip_test] -%>
27
+ test:
28
+ runs-on: ubuntu-latest
29
+
30
+ <%- if options[:database] == "sqlite3" -%>
31
+ # services:
32
+ # redis:
33
+ # image: redis
34
+ # ports:
35
+ # - 6379:6379
36
+ # options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
37
+ <%- else -%>
38
+ services:
39
+ <%- if options[:database] == "mysql" || options[:database] == "trilogy" -%>
40
+ mysql:
41
+ image: mysql
42
+ env:
43
+ MYSQL_ALLOW_EMPTY_PASSWORD: true
44
+ ports:
45
+ - 3306:3306
46
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
47
+ <%- elsif options[:database] == "postgresql" -%>
48
+ postgres:
49
+ image: postgres
50
+ env:
51
+ POSTGRES_USER: postgres
52
+ POSTGRES_PASSWORD: postgres
53
+ ports:
54
+ - 5432:5432
55
+ options: --health-cmd="pg_isready" --health-interval=10s --health-timeout=5s --health-retries=3
56
+ <%- end -%>
57
+
58
+ # redis:
59
+ # image: redis
60
+ # ports:
61
+ # - 6379:6379
62
+ # options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
63
+
64
+ <%- end -%>
65
+ steps:
66
+ - name: Install packages
67
+ run: sudo apt-get update && sudo apt-get install --no-install-recommends -y <%= ci_packages.join(" ") %>
68
+
69
+ - name: Checkout code
70
+ uses: actions/checkout@v4
71
+
72
+ - name: Set up Ruby
73
+ uses: ruby/setup-ruby@v1
74
+ with:
75
+ ruby-version: <%= ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}" %>
76
+ bundler-cache: true
77
+ <%- if using_bun? -%>
78
+
79
+ - uses: oven-sh/setup-bun@v1
80
+ with:
81
+ bun-version: <%= dockerfile_bun_version %>
82
+ <%- end -%>
83
+
84
+ - name: Run tests
85
+ env:
86
+ RAILS_ENV: test
87
+ <%- if options[:database] == "mysql" || options[:database] == "trilogy" -%>
88
+ DATABASE_URL: mysql2://127.0.0.1:3306
89
+ <%- elsif options[:database] == "postgresql" -%>
90
+ DATABASE_URL: postgres://postgres:postgres@localhost:5432
91
+ <%- end -%>
92
+ # REDIS_URL: redis://localhost:6379/0
93
+ run: <%= test_command %>
94
+
95
+ - name: Keep screenshots from failed system tests
96
+ uses: actions/upload-artifact@v4
97
+ if: failure()
98
+ with:
99
+ name: screenshots
100
+ path: ${{ github.workspace }}/tmp/screenshots
101
+ if-no-files-found: ignore
102
+ <% end -%>
103
+
@@ -0,0 +1,12 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ open-pull-requests-limit: 10
8
+ - package-ecosystem: github-actions
9
+ directory: "/"
10
+ schedule:
11
+ interval: daily
12
+ open-pull-requests-limit: 10
@@ -0,0 +1,8 @@
1
+ # Omakase Ruby styling for Rails
2
+ inherit_gem: { rubocop-rails-omakase: rubocop.yml }
3
+
4
+ # Overwrite or add rules to create your own house style
5
+ #
6
+ # # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
7
+ # Layout/SpaceInsideArrayLiteralBrackets:
8
+ # Enabled: false
@@ -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
@@ -3,7 +3,7 @@ ENV["RAILS_ENV"] = "test"
3
3
 
4
4
  require_relative "<%= File.join("..", options[:dummy_path], "config/environment") -%>"
5
5
  <% unless options[:skip_active_record] -%>
6
- ActiveRecord::Migrator.migrations_paths = [File.expand_path("../<%= options[:dummy_path] -%>/db/migrate", __dir__)]
6
+ ActiveRecord::Migrator.migrations_paths = [ File.expand_path("../<%= options[:dummy_path] -%>/db/migrate", __dir__) ]
7
7
  <% if options[:mountable] -%>
8
8
  ActiveRecord::Migrator.migrations_paths << File.expand_path("../db/migrate", __dir__)
9
9
  <% end -%>
@@ -13,7 +13,7 @@ require "rails/test_help"
13
13
  <% unless options[:skip_active_record] -%>
14
14
  # Load fixtures from the engine
15
15
  if ActiveSupport::TestCase.respond_to?(:fixture_paths=)
16
- ActiveSupport::TestCase.fixture_paths = [File.expand_path("fixtures", __dir__)]
16
+ ActiveSupport::TestCase.fixture_paths = [ File.expand_path("fixtures", __dir__) ]
17
17
  ActionDispatch::IntegrationTest.fixture_paths = ActiveSupport::TestCase.fixture_paths
18
18
  ActiveSupport::TestCase.file_fixture_path = File.expand_path("fixtures", __dir__) + "/files"
19
19
  ActiveSupport::TestCase.fixtures :all
@@ -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
@@ -43,13 +43,13 @@ class <%= controller_class_name %>Controller < ApplicationController
43
43
  # DELETE <%= route_url %>/1
44
44
  def destroy
45
45
  @<%= orm_instance.destroy %>
46
- redirect_to <%= index_helper %>_url, notice: <%= %("#{human_name} was successfully destroyed.") %>, status: :see_other
46
+ redirect_to <%= index_helper %>_path, notice: <%= %("#{human_name} was successfully destroyed.") %>, status: :see_other
47
47
  end
48
48
 
49
49
  private
50
50
  # Use callbacks to share common setup or constraints between actions.
51
51
  def set_<%= singular_table_name %>
52
- @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
52
+ @<%= singular_table_name %> = <%= orm_class.find(class_name, "params.expect(:id)") %>
53
53
  end
54
54
 
55
55
  # Only allow a list of trusted parameters through.
@@ -57,7 +57,7 @@ class <%= controller_class_name %>Controller < ApplicationController
57
57
  <%- if attributes_names.empty? -%>
58
58
  params.fetch(:<%= singular_table_name %>, {})
59
59
  <%- else -%>
60
- params.require(:<%= singular_table_name %>).permit(<%= permitted_params %>)
60
+ params.expect(<%= singular_table_name %>: [ <%= permitted_params %> ])
61
61
  <%- end -%>
62
62
  end
63
63
  end
@@ -0,0 +1,18 @@
1
+ Description:
2
+ Generate a one-off or general purpose script, such as a data migration
3
+ script, cleanup script, etc.
4
+
5
+ Example:
6
+ `bin/rails generate script my_script`
7
+
8
+ This will create:
9
+ script/my_script.rb
10
+
11
+ You can run the script using:
12
+ `ruby script/my_script.rb`
13
+
14
+ You can specify a folder:
15
+ `bin/rails generate script cleanup/my_script`
16
+
17
+ This will create:
18
+ script/cleanup/my_script.rb
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/named_base"
4
+
5
+ module Rails
6
+ module Generators
7
+ class ScriptGenerator < NamedBase
8
+ def generate_script
9
+ template("script.rb.tt", "script/#{file_path}.rb")
10
+ end
11
+
12
+ private
13
+ def depth
14
+ class_path.size + 1
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ require_relative "<%= '../' * depth %>config/environment"
2
+
3
+ # Your code goes here
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/test_unit"
4
+
5
+ module TestUnit # :nodoc:
6
+ module Generators # :nodoc:
7
+ class AuthenticationGenerator < Rails::Generators::Base # :nodoc:
8
+ def create_user_test_files
9
+ template "test/fixtures/users.yml"
10
+ template "test/models/user_test.rb"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ <%% password_digest = BCrypt::Password.create("password") %>
2
+
3
+ one:
4
+ email_address: one@example.com
5
+ password_digest: <%%= password_digest %>
6
+
7
+ two:
8
+ email_address: two@example.com
9
+ password_digest: <%%= password_digest %>
@@ -0,0 +1,7 @@
1
+ require "test_helper"
2
+
3
+ class UserTest < ActiveSupport::TestCase
4
+ # test "the truth" do
5
+ # assert true
6
+ # end
7
+ end
@@ -2,15 +2,17 @@ require "test_helper"
2
2
 
3
3
  <% module_namespacing do -%>
4
4
  class <%= class_name %>MailerTest < ActionMailer::TestCase
5
- <% actions.each do |action| -%>
5
+ <% actions.each_with_index do |action, index| -%>
6
+ <% if index != 0 -%>
7
+
8
+ <% end -%>
6
9
  test "<%= action %>" do
7
10
  mail = <%= class_name %>Mailer.<%= action %>
8
11
  assert_equal <%= action.to_s.humanize.inspect %>, mail.subject
9
- assert_equal ["to@example.org"], mail.to
10
- assert_equal ["from@example.com"], mail.from
12
+ assert_equal [ "to@example.org" ], mail.to
13
+ assert_equal [ "from@example.com" ], mail.from
11
14
  assert_match "Hi", mail.body.encoded
12
15
  end
13
-
14
16
  <% end -%>
15
17
  <% if actions.blank? -%>
16
18
  # test "the truth" do
@@ -1,13 +1,14 @@
1
1
  <% module_namespacing do -%>
2
2
  # Preview all emails at http://localhost:3000/rails/mailers/<%= file_path %>_mailer
3
3
  class <%= class_name %>MailerPreview < ActionMailer::Preview
4
- <% actions.each do |action| -%>
4
+ <% actions.each_with_index do |action, index| -%>
5
+ <% if index != 0 -%>
5
6
 
7
+ <% end -%>
6
8
  # Preview this email at http://localhost:3000/rails/mailers/<%= file_path %>_mailer/<%= action %>
7
9
  def <%= action %>
8
10
  <%= class_name %>Mailer.<%= action %>
9
11
  end
10
12
  <% end -%>
11
-
12
13
  end
13
14
  <% end -%>
@@ -39,7 +39,11 @@ module TestUnit # :nodoc:
39
39
 
40
40
  private
41
41
  def attributes_string
42
- attributes_hash.map { |k, v| "#{k}: #{v}" }.join(", ")
42
+ if attributes_hash.empty?
43
+ "{}"
44
+ else
45
+ "{ #{attributes_hash.map { |k, v| "#{k}: #{v}" }.join(", ")} }"
46
+ end
43
47
  end
44
48
 
45
49
  def attributes_hash
@@ -63,6 +67,16 @@ module TestUnit # :nodoc:
63
67
  attribute = attributes.find { |attr| attr.name == name }
64
68
  attribute&.virtual?
65
69
  end
70
+
71
+ def datetime?(name)
72
+ attribute = attributes.find { |attr| attr.name == name }
73
+ attribute&.type == :datetime
74
+ end
75
+
76
+ def time?(name)
77
+ attribute = attributes.find { |attr| attr.name == name }
78
+ attribute&.type == :time
79
+ end
66
80
  end
67
81
  end
68
82
  end
@@ -17,7 +17,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
17
17
 
18
18
  test "should create <%= singular_table_name %>" do
19
19
  assert_difference("<%= class_name %>.count") do
20
- post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: { #{attributes_string} }" %> }, as: :json
20
+ post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: #{attributes_string}" %> }, as: :json
21
21
  end
22
22
 
23
23
  assert_response :created
@@ -29,7 +29,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
29
29
  end
30
30
 
31
31
  test "should update <%= singular_table_name %>" do
32
- patch <%= show_helper %>, params: { <%= "#{singular_table_name}: { #{attributes_string} }" %> }, as: :json
32
+ patch <%= show_helper %>, params: { <%= "#{singular_table_name}: #{attributes_string}" %> }, as: :json
33
33
  assert_response :success
34
34
  end
35
35
 
@@ -22,7 +22,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
22
22
 
23
23
  test "should create <%= singular_table_name %>" do
24
24
  assert_difference("<%= class_name %>.count") do
25
- post <%= index_helper(type: :url) %>, params: { <%= "#{singular_table_name}: { #{attributes_string} }" %> }
25
+ post <%= index_helper(type: :url) %>, params: { <%= "#{singular_table_name}: #{attributes_string}" %> }
26
26
  end
27
27
 
28
28
  assert_redirected_to <%= show_helper("#{class_name}.last") %>
@@ -39,7 +39,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
39
39
  end
40
40
 
41
41
  test "should update <%= singular_table_name %>" do
42
- patch <%= show_helper %>, params: { <%= "#{singular_table_name}: { #{attributes_string} }" %> }
42
+ patch <%= show_helper %>, params: { <%= "#{singular_table_name}: #{attributes_string}" %> }
43
43
  assert_redirected_to <%= show_helper %>
44
44
  end
45
45
 
@@ -35,6 +35,8 @@ class <%= class_name.pluralize %>Test < ApplicationSystemTestCase
35
35
  <%- attributes_hash.each do |attr, value| -%>
36
36
  <%- if boolean?(attr) -%>
37
37
  check "<%= attr.humanize %>" if <%= value %>
38
+ <%- elsif datetime?(attr) || time?(attr) -%>
39
+ fill_in "<%= attr.humanize %>", with: <%= value %>.to_s
38
40
  <%- else -%>
39
41
  fill_in "<%= attr.humanize %>", with: <%= value %>
40
42
  <%- end -%>
@@ -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
@@ -60,6 +60,10 @@ module Rails
60
60
  }
61
61
  }
62
62
 
63
+ # We need to store the RAILS_DEV_PATH in a constant, otherwise the path
64
+ # can change when we FileUtils.cd.
65
+ RAILS_DEV_PATH = File.expand_path("../../..", __dir__) # :nodoc:
66
+
63
67
  class << self
64
68
  def configure!(config) # :nodoc:
65
69
  api_only! if config.api_only
@@ -151,7 +155,8 @@ module Rails
151
155
  "#{template}:scaffold",
152
156
  "#{template}:mailer",
153
157
  "action_text:install",
154
- "action_mailbox:install"
158
+ "action_mailbox:install",
159
+ "devcontainer"
155
160
  ]
156
161
  end
157
162
  end
@@ -202,7 +207,6 @@ module Rails
202
207
  rails.map! { |n| n.delete_prefix("rails:") }
203
208
  rails.delete("app")
204
209
  rails.delete("plugin")
205
- rails.delete("encrypted_secrets")
206
210
  rails.delete("encrypted_file")
207
211
  rails.delete("encryption_key_file")
208
212
  rails.delete("master_key")
@@ -268,6 +272,7 @@ module Rails
268
272
  #{error.detailed_message}
269
273
  Run `bin/rails generate --help` for more options.
270
274
  MSG
275
+ exit 1
271
276
  end
272
277
  end
273
278
 
@@ -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
@@ -20,7 +20,7 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
20
20
 
21
21
  def routes
22
22
  if query = params[:query]
23
- query = URI::DEFAULT_PARSER.escape query
23
+ query = URI::RFC2396_PARSER.escape query
24
24
 
25
25
  render json: {
26
26
  exact: matching_routes(query: query, exact_match: true),
@@ -32,6 +32,14 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
32
32
  end
33
33
  end
34
34
 
35
+ def notes
36
+ @annotations = Rails::SourceAnnotationExtractor.new(
37
+ Rails::SourceAnnotationExtractor::Annotation.tags.join("|")
38
+ ).find(
39
+ Rails::SourceAnnotationExtractor::Annotation.directories
40
+ )
41
+ end
42
+
35
43
  private
36
44
  def matching_routes(query:, exact_match:)
37
45
  return [] if query.blank?
@@ -53,7 +61,7 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
53
61
  match ||= (query === route_wrapper.verb)
54
62
 
55
63
  unless match
56
- controller_action = URI::DEFAULT_PARSER.escape(route_wrapper.reqs)
64
+ controller_action = URI::RFC2396_PARSER.escape(route_wrapper.reqs)
57
65
  match = exact_match ? (query === controller_action) : controller_action.include?(query)
58
66
  end
59
67
 
@@ -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