railties 7.2.0 → 8.0.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +111 -254
- data/lib/minitest/rails_plugin.rb +1 -1
- data/lib/rails/application/configuration.rb +15 -2
- data/lib/rails/application/default_middleware_stack.rb +4 -0
- data/lib/rails/application/finisher.rb +2 -2
- data/lib/rails/application/routes_reloader.rb +11 -1
- data/lib/rails/application.rb +12 -0
- data/lib/rails/code_statistics.rb +128 -86
- data/lib/rails/code_statistics_calculator.rb +78 -76
- data/lib/rails/command/helpers/editor.rb +1 -1
- data/lib/rails/commands/app/update_command.rb +10 -9
- data/lib/rails/commands/console/irb_console.rb +1 -2
- data/lib/rails/commands/credentials/USAGE +4 -4
- data/lib/rails/commands/credentials/credentials_command.rb +5 -1
- data/lib/rails/commands/dev/dev_command.rb +1 -1
- data/lib/rails/commands/devcontainer/devcontainer_command.rb +1 -1
- data/lib/rails/commands/stats/stats_command.rb +19 -0
- data/lib/rails/dev_caching.rb +2 -2
- data/lib/rails/engine/configuration.rb +3 -1
- data/lib/rails/engine/lazy_route_set.rb +109 -0
- data/lib/rails/engine.rb +10 -5
- data/lib/rails/gem_version.rb +3 -3
- data/lib/rails/generators/app_base.rb +46 -24
- data/lib/rails/generators/database.rb +102 -68
- data/lib/rails/generators/erb/authentication/authentication_generator.rb +15 -0
- data/lib/rails/generators/erb/authentication/templates/views/passwords/edit.html.erb +9 -0
- data/lib/rails/generators/erb/authentication/templates/views/passwords/new.html.erb +8 -0
- data/lib/rails/generators/erb/authentication/templates/views/sessions/new.html.erb +11 -0
- data/lib/rails/generators/generated_attribute.rb +16 -11
- data/lib/rails/generators/rails/app/app_generator.rb +22 -32
- data/lib/rails/generators/rails/app/templates/Dockerfile.tt +12 -3
- data/lib/rails/generators/rails/app/templates/Gemfile.tt +23 -8
- data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +6 -11
- data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +10 -3
- data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +3 -3
- data/lib/rails/generators/rails/app/templates/bin/dev.tt +1 -0
- data/lib/rails/generators/rails/app/templates/bin/setup.tt +5 -7
- data/lib/rails/generators/rails/app/templates/bin/thrust.tt +4 -0
- data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +23 -0
- data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +23 -0
- data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +40 -0
- data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +23 -0
- data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +124 -0
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +12 -23
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +34 -51
- data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +5 -19
- data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +0 -7
- data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +25 -0
- data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +13 -3
- data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +5 -3
- data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +4 -3
- data/lib/rails/generators/rails/app/templates/dockerignore.tt +1 -2
- data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +1 -1
- data/lib/rails/generators/rails/app/templates/gitignore.tt +1 -2
- data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +17 -0
- data/lib/rails/generators/rails/app/templates/public/400.html +114 -0
- data/lib/rails/generators/rails/app/templates/public/404.html +113 -66
- data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +113 -65
- data/lib/rails/generators/rails/app/templates/public/422.html +113 -66
- data/lib/rails/generators/rails/app/templates/public/500.html +113 -65
- data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
- data/lib/rails/generators/rails/app/templates/public/icon.svg +2 -2
- data/lib/rails/generators/rails/authentication/USAGE +6 -0
- data/lib/rails/generators/rails/authentication/authentication_generator.rb +54 -0
- data/lib/rails/generators/rails/authentication/templates/controllers/concerns/authentication.rb +55 -0
- data/lib/rails/generators/rails/authentication/templates/controllers/passwords_controller.rb +33 -0
- data/lib/rails/generators/rails/authentication/templates/controllers/sessions_controller.rb +21 -0
- data/lib/rails/generators/rails/authentication/templates/mailers/passwords_mailer.rb +6 -0
- data/lib/rails/generators/rails/authentication/templates/models/current.rb +4 -0
- data/lib/rails/generators/rails/authentication/templates/models/session.rb +3 -0
- data/lib/rails/generators/rails/authentication/templates/models/user.rb +6 -0
- data/lib/rails/generators/rails/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb +7 -0
- data/lib/rails/generators/rails/authentication/templates/views/passwords_mailer/reset.html.erb +4 -0
- data/lib/rails/generators/rails/authentication/templates/views/passwords_mailer/reset.text.erb +2 -0
- data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +4 -0
- data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
- data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +5 -3
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +1 -1
- data/lib/rails/generators/rails/plugin/plugin_generator.rb +11 -11
- data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +1 -1
- data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -2
- data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
- data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +3 -3
- data/lib/rails/generators/rails/script/USAGE +18 -0
- data/lib/rails/generators/rails/script/script_generator.rb +18 -0
- data/lib/rails/generators/rails/script/templates/script.rb.tt +3 -0
- data/lib/rails/generators.rb +7 -2
- data/lib/rails/info_controller.rb +10 -2
- data/lib/rails/rack/silence_request.rb +33 -0
- data/lib/rails/rack.rb +1 -0
- data/lib/rails/railtie.rb +13 -13
- data/lib/rails/source_annotation_extractor.rb +31 -14
- data/lib/rails/tasks/statistics.rake +13 -28
- data/lib/rails/templates/rails/info/notes.html.erb +65 -0
- metadata +45 -25
- data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -2
- data/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt +0 -4
- data/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt +0 -4
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +0 -70
- data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +0 -13
- data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +0 -13
- data/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt +0 -10
- data/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt +0 -6
- data/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt +0 -17
| @@ -1,66 +1,114 @@ | |
| 1 | 
            -
            <! | 
| 2 | 
            -
             | 
| 3 | 
            -
            < | 
| 4 | 
            -
             | 
| 5 | 
            -
              < | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
                 | 
| 10 | 
            -
                 | 
| 11 | 
            -
                 | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 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>
         | 
| Binary file | 
| @@ -1,3 +1,3 @@ | |
| 1 | 
            -
            <svg width=" | 
| 2 | 
            -
              < | 
| 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>
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Rails
         | 
| 4 | 
            +
              module Generators
         | 
| 5 | 
            +
                class AuthenticationGenerator < Base # :nodoc:
         | 
| 6 | 
            +
                  class_option :api, type: :boolean,
         | 
| 7 | 
            +
                    desc: "Generate API-only controllers and models, with no view templates"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  hook_for :template_engine, as: :authentication do |template_engine|
         | 
| 10 | 
            +
                    invoke template_engine unless options.api?
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def create_authentication_files
         | 
| 14 | 
            +
                    template "models/session.rb", File.join("app/models/session.rb")
         | 
| 15 | 
            +
                    template "models/user.rb", File.join("app/models/user.rb")
         | 
| 16 | 
            +
                    template "models/current.rb", File.join("app/models/current.rb")
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    template "controllers/sessions_controller.rb", File.join("app/controllers/sessions_controller.rb")
         | 
| 19 | 
            +
                    template "controllers/concerns/authentication.rb", File.join("app/controllers/concerns/authentication.rb")
         | 
| 20 | 
            +
                    template "controllers/passwords_controller.rb", File.join("app/controllers/passwords_controller.rb")
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    template "mailers/passwords_mailer.rb", File.join("app/mailers/passwords_mailer.rb")
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    template "views/passwords_mailer/reset.html.erb", File.join("app/views/passwords_mailer/reset.html.erb")
         | 
| 25 | 
            +
                    template "views/passwords_mailer/reset.text.erb", File.join("app/views/passwords_mailer/reset.text.erb")
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    template "test/mailers/previews/passwords_mailer_preview.rb", File.join("test/mailers/previews/passwords_mailer_preview.rb")
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def configure_application_controller
         | 
| 31 | 
            +
                    gsub_file "app/controllers/application_controller.rb", /(class ApplicationController < ActionController::Base)/, "\\1\n  include Authentication"
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def configure_authentication_routes
         | 
| 35 | 
            +
                    route "resources :passwords, param: :token"
         | 
| 36 | 
            +
                    route "resource :session"
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def enable_bcrypt
         | 
| 40 | 
            +
                    if File.read("Gemfile").include?('gem "bcrypt"')
         | 
| 41 | 
            +
                      uncomment_lines "Gemfile", /gem "bcrypt"/
         | 
| 42 | 
            +
                      Bundler.with_original_env { execute_command :bundle, "install --quiet" }
         | 
| 43 | 
            +
                    else
         | 
| 44 | 
            +
                      Bundler.with_original_env { execute_command :bundle, "add bcrypt --quiet" }
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def add_migrations
         | 
| 49 | 
            +
                    generate "migration CreateUsers email_address:string!:uniq password_digest:string! --force"
         | 
| 50 | 
            +
                    generate "migration CreateSessions user:references ip_address:string user_agent:string --force"
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
    
        data/lib/rails/generators/rails/authentication/templates/controllers/concerns/authentication.rb
    ADDED
    
    | @@ -0,0 +1,55 @@ | |
| 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 | 
            +
                  Current.session.present?
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def require_authentication
         | 
| 21 | 
            +
                  resume_session || request_authentication
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| 25 | 
            +
                def resume_session
         | 
| 26 | 
            +
                  Current.session = find_session_by_cookie
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def find_session_by_cookie
         | 
| 30 | 
            +
                  Session.find_by(id: cookies.signed[:session_id])
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
             | 
| 34 | 
            +
                def request_authentication
         | 
| 35 | 
            +
                  session[:return_to_after_authenticating] = request.url
         | 
| 36 | 
            +
                  redirect_to new_session_url
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def after_authentication_url
         | 
| 40 | 
            +
                  session.delete(:return_to_after_authenticating) || root_url
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
             | 
| 44 | 
            +
                def start_new_session_for(user)
         | 
| 45 | 
            +
                  user.sessions.create!(user_agent: request.user_agent, ip_address: request.remote_ip).tap do |session|
         | 
| 46 | 
            +
                    Current.session = session
         | 
| 47 | 
            +
                    cookies.signed.permanent[:session_id] = { value: session.id, httponly: true, same_site: :lax }
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def terminate_session
         | 
| 52 | 
            +
                  Current.session.destroy
         | 
| 53 | 
            +
                  cookies.delete(:session_id)
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
            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_url, 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_url, notice: "Password has been reset."
         | 
| 22 | 
            +
                else
         | 
| 23 | 
            +
                  redirect_to edit_password_url(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_url, 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_url, alert: "Try another email address or password."
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def destroy
         | 
| 18 | 
            +
                terminate_session
         | 
| 19 | 
            +
                redirect_to new_session_url
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            # Preview all emails at http://localhost:3000/rails/mailers/passwords_mailer
         | 
| 2 | 
            +
            class PasswordsMailerPreview < ActionMailer::Preview
         | 
| 3 | 
            +
              # Preview this email at http://localhost:3000/rails/mailers/passwords_mailer/reset
         | 
| 4 | 
            +
              def reset
         | 
| 5 | 
            +
                PasswordsMailer.reset(User.take)
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
            end
         | 
| @@ -38,9 +38,11 @@ module Rails | |
| 38 38 |  | 
| 39 39 | 
             
                  def update_application_system_test_case
         | 
| 40 40 | 
             
                    return unless options[:system_test]
         | 
| 41 | 
            -
                    return unless File.exist?("test/application_system_test_case.rb")
         | 
| 42 41 |  | 
| 43 | 
            -
                     | 
| 42 | 
            +
                    system_test_case_path = File.expand_path "test/application_system_test_case.rb", destination_root
         | 
| 43 | 
            +
                    return unless File.exist? system_test_case_path
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    gsub_file(system_test_case_path, /^\s*driven_by\b.*/, system_test_configuration)
         | 
| 44 46 | 
             
                  end
         | 
| 45 47 |  | 
| 46 48 | 
             
                  def update_database_yml
         | 
| @@ -148,7 +150,7 @@ module Rails | |
| 148 150 | 
             
                    end
         | 
| 149 151 |  | 
| 150 152 | 
             
                    def system_test_configuration
         | 
| 151 | 
            -
                      optimize_indentation(<<-'RUBY', 2)
         | 
| 153 | 
            +
                      optimize_indentation(<<-'RUBY', 2).chomp
         | 
| 152 154 | 
             
                        if ENV["CAPYBARA_SERVER_PORT"]
         | 
| 153 155 | 
             
                          served_by host: "rails-app", port: ENV["CAPYBARA_SERVER_PORT"]
         | 
| 154 156 |  | 
| @@ -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  | 
| 153 | 
            -
                  template "rails/stylesheets.css", | 
| 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 | 
            -
                     | 
| 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(: | 
| 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)
         | 
| @@ -491,9 +489,11 @@ module Rails | |
| 491 489 |  | 
| 492 490 | 
             
                  def test_command
         | 
| 493 491 | 
             
                    if engine? && !options[:skip_active_record] && with_dummy_app?
         | 
| 494 | 
            -
                      "db:test:prepare test"
         | 
| 492 | 
            +
                      "bin/rails db:test:prepare test"
         | 
| 493 | 
            +
                    elsif engine?
         | 
| 494 | 
            +
                      "bin/rails test"
         | 
| 495 495 | 
             
                    else
         | 
| 496 | 
            -
                      "test"
         | 
| 496 | 
            +
                      "bin/test"
         | 
| 497 497 | 
             
                    end
         | 
| 498 498 | 
             
                  end
         | 
| 499 499 | 
             
                end
         | 
| @@ -90,7 +90,7 @@ jobs: | |
| 90 90 | 
             
                      DATABASE_URL: postgres://postgres:postgres@localhost:5432
         | 
| 91 91 | 
             
                      <%- end -%>
         | 
| 92 92 | 
             
                      # REDIS_URL: redis://localhost:6379/0
         | 
| 93 | 
            -
                    run:  | 
| 93 | 
            +
                    run: <%= test_command %>
         | 
| 94 94 |  | 
| 95 95 | 
             
                  - name: Keep screenshots from failed system tests
         | 
| 96 96 | 
             
                    uses: actions/upload-artifact@v4
         | 
| @@ -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 | 
| 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. | 
| 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 %> | 
| 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 | 
| 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. | 
| 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
         |