railties 7.0.8.7 → 7.1.5.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 (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +723 -215
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.md +99 -0
  5. data/README.rdoc +4 -4
  6. data/lib/minitest/rails_plugin.rb +63 -0
  7. data/lib/rails/api/task.rb +35 -4
  8. data/lib/rails/app_updater.rb +14 -2
  9. data/lib/rails/application/bootstrap.rb +23 -4
  10. data/lib/rails/application/configuration.rb +190 -69
  11. data/lib/rails/application/default_middleware_stack.rb +8 -2
  12. data/lib/rails/application/dummy_config.rb +19 -0
  13. data/lib/rails/application/finisher.rb +43 -33
  14. data/lib/rails/application.rb +141 -33
  15. data/lib/rails/backtrace_cleaner.rb +5 -3
  16. data/lib/rails/cli.rb +5 -2
  17. data/lib/rails/command/actions.rb +10 -12
  18. data/lib/rails/command/base.rb +55 -53
  19. data/lib/rails/command/environment_argument.rb +32 -16
  20. data/lib/rails/command/helpers/editor.rb +17 -12
  21. data/lib/rails/command.rb +84 -33
  22. data/lib/rails/commands/about/about_command.rb +14 -0
  23. data/lib/rails/commands/application/application_command.rb +2 -0
  24. data/lib/rails/commands/console/console_command.rb +14 -14
  25. data/lib/rails/commands/credentials/USAGE +53 -55
  26. data/lib/rails/commands/credentials/credentials_command/diffing.rb +5 -3
  27. data/lib/rails/commands/credentials/credentials_command.rb +64 -70
  28. data/lib/rails/commands/db/system/change/change_command.rb +2 -1
  29. data/lib/rails/commands/dbconsole/dbconsole_command.rb +25 -115
  30. data/lib/rails/commands/destroy/destroy_command.rb +3 -2
  31. data/lib/rails/commands/dev/dev_command.rb +1 -6
  32. data/lib/rails/commands/encrypted/USAGE +15 -20
  33. data/lib/rails/commands/encrypted/encrypted_command.rb +46 -35
  34. data/lib/rails/commands/gem_help/USAGE +16 -0
  35. data/lib/rails/commands/gem_help/gem_help_command.rb +13 -0
  36. data/lib/rails/commands/generate/generate_command.rb +2 -2
  37. data/lib/rails/commands/help/USAGE +13 -13
  38. data/lib/rails/commands/help/help_command.rb +21 -2
  39. data/lib/rails/commands/initializers/initializers_command.rb +1 -4
  40. data/lib/rails/commands/middleware/middleware_command.rb +17 -0
  41. data/lib/rails/commands/new/new_command.rb +2 -0
  42. data/lib/rails/commands/notes/notes_command.rb +2 -1
  43. data/lib/rails/commands/plugin/plugin_command.rb +2 -0
  44. data/lib/rails/commands/rake/rake_command.rb +25 -22
  45. data/lib/rails/commands/restart/restart_command.rb +14 -0
  46. data/lib/rails/commands/routes/routes_command.rb +13 -1
  47. data/lib/rails/commands/runner/USAGE +14 -12
  48. data/lib/rails/commands/runner/runner_command.rb +32 -20
  49. data/lib/rails/commands/secret/secret_command.rb +13 -0
  50. data/lib/rails/commands/secrets/USAGE +44 -49
  51. data/lib/rails/commands/secrets/secrets_command.rb +20 -38
  52. data/lib/rails/commands/server/server_command.rb +33 -32
  53. data/lib/rails/commands/test/USAGE +14 -0
  54. data/lib/rails/commands/test/test_command.rb +56 -14
  55. data/lib/rails/commands/unused_routes/unused_routes_command.rb +75 -0
  56. data/lib/rails/commands/version/version_command.rb +1 -0
  57. data/lib/rails/configuration.rb +5 -5
  58. data/lib/rails/console/app.rb +1 -4
  59. data/lib/rails/deprecator.rb +7 -0
  60. data/lib/rails/engine/configuration.rb +50 -6
  61. data/lib/rails/engine.rb +49 -21
  62. data/lib/rails/gem_version.rb +4 -4
  63. data/lib/rails/generators/actions.rb +6 -15
  64. data/lib/rails/generators/active_model.rb +28 -14
  65. data/lib/rails/generators/app_base.rb +355 -82
  66. data/lib/rails/generators/app_name.rb +3 -14
  67. data/lib/rails/generators/base.rb +17 -9
  68. data/lib/rails/generators/database.rb +40 -2
  69. data/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt +1 -1
  70. data/lib/rails/generators/generated_attribute.rb +12 -0
  71. data/lib/rails/generators/migration.rb +4 -5
  72. data/lib/rails/generators/model_helpers.rb +2 -1
  73. data/lib/rails/generators/rails/app/USAGE +22 -6
  74. data/lib/rails/generators/rails/app/app_generator.rb +85 -64
  75. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +103 -0
  76. data/lib/rails/generators/rails/app/templates/Gemfile.tt +9 -11
  77. data/lib/rails/generators/rails/app/templates/app/views/layouts/mailer.html.erb.tt +1 -1
  78. data/lib/rails/generators/rails/app/templates/bin/setup.tt +10 -1
  79. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +6 -17
  80. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +4 -4
  81. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +3 -3
  82. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +4 -6
  83. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +3 -3
  84. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +59 -0
  85. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +12 -2
  86. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +32 -28
  87. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +13 -9
  88. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +2 -0
  89. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +2 -2
  90. data/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt +1 -1
  91. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +3 -3
  92. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +280 -0
  93. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +11 -9
  94. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +11 -13
  95. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +21 -20
  96. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +5 -1
  97. data/lib/rails/generators/rails/app/templates/db/seeds.rb.tt +6 -4
  98. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +10 -0
  99. data/lib/rails/generators/rails/app/templates/dockerignore.tt +43 -0
  100. data/lib/rails/generators/rails/app/templates/gitignore.tt +4 -8
  101. data/lib/rails/generators/rails/app/templates/node-version.tt +1 -0
  102. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +10 -8
  103. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +9 -7
  104. data/lib/rails/generators/rails/application_record/application_record_generator.rb +4 -0
  105. data/lib/rails/generators/rails/benchmark/benchmark_generator.rb +2 -1
  106. data/lib/rails/generators/rails/controller/USAGE +12 -4
  107. data/lib/rails/generators/rails/controller/controller_generator.rb +5 -0
  108. data/lib/rails/generators/rails/controller/templates/controller.rb.tt +1 -1
  109. data/lib/rails/generators/rails/credentials/credentials_generator.rb +29 -24
  110. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +8 -0
  111. data/lib/rails/generators/rails/db/system/change/change_generator.rb +30 -0
  112. data/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb +1 -2
  113. data/lib/rails/generators/rails/migration/USAGE +21 -11
  114. data/lib/rails/generators/rails/model/model_generator.rb +4 -0
  115. data/lib/rails/generators/rails/plugin/USAGE +17 -6
  116. data/lib/rails/generators/rails/plugin/plugin_generator.rb +5 -15
  117. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +2 -2
  118. data/lib/rails/generators/rails/plugin/templates/MIT-LICENSE.tt +1 -1
  119. data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +1 -17
  120. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +0 -2
  121. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +4 -4
  122. data/lib/rails/generators/rails/resource/resource_generator.rb +6 -0
  123. data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +2 -1
  124. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +1 -1
  125. data/lib/rails/generators/test_case.rb +2 -2
  126. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +1 -1
  127. data/lib/rails/generators/testing/{behaviour.rb → behavior.rb} +4 -1
  128. data/lib/rails/generators.rb +6 -14
  129. data/lib/rails/health_controller.rb +55 -0
  130. data/lib/rails/info.rb +1 -1
  131. data/lib/rails/info_controller.rb +33 -11
  132. data/lib/rails/mailers_controller.rb +15 -5
  133. data/lib/rails/paths.rb +13 -10
  134. data/lib/rails/rack/logger.rb +15 -12
  135. data/lib/rails/rackup/server.rb +15 -0
  136. data/lib/rails/railtie/configuration.rb +14 -1
  137. data/lib/rails/railtie.rb +31 -31
  138. data/lib/rails/ruby_version_check.rb +2 -0
  139. data/lib/rails/source_annotation_extractor.rb +67 -18
  140. data/lib/rails/tasks/engine.rake +8 -8
  141. data/lib/rails/tasks/framework.rake +4 -10
  142. data/lib/rails/tasks/log.rake +1 -1
  143. data/lib/rails/tasks/misc.rake +3 -14
  144. data/lib/rails/tasks/statistics.rake +5 -4
  145. data/lib/rails/tasks/tmp.rake +5 -5
  146. data/lib/rails/tasks/zeitwerk.rake +15 -35
  147. data/lib/rails/tasks.rb +0 -2
  148. data/lib/rails/templates/rails/mailers/email.html.erb +32 -0
  149. data/lib/rails/templates/rails/mailers/index.html.erb +14 -7
  150. data/lib/rails/templates/rails/mailers/mailer.html.erb +11 -5
  151. data/lib/rails/templates/rails/welcome/index.html.erb +1 -0
  152. data/lib/rails/test_help.rb +9 -14
  153. data/lib/rails/test_unit/line_filtering.rb +1 -1
  154. data/lib/rails/test_unit/reporter.rb +6 -2
  155. data/lib/rails/test_unit/runner.rb +36 -18
  156. data/lib/rails/test_unit/test_parser.rb +88 -0
  157. data/lib/rails/test_unit/testing.rake +13 -33
  158. data/lib/rails/testing/maintain_test_schema.rb +16 -0
  159. data/lib/rails/version.rb +1 -1
  160. data/lib/rails/zeitwerk_checker.rb +15 -0
  161. data/lib/rails.rb +15 -15
  162. metadata +64 -27
  163. data/RDOC_MAIN.rdoc +0 -97
  164. data/lib/rails/application/dummy_erb_compiler.rb +0 -18
  165. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +0 -143
  166. data/lib/rails/generators/rails/model/USAGE +0 -113
  167. data/lib/rails/tasks/middleware.rake +0 -9
  168. data/lib/rails/tasks/restart.rake +0 -9
@@ -1,20 +1,22 @@
1
- Examples:
1
+ Description:
2
+ The Rails `runner` allows running Ruby code in the context of your application.
2
3
 
3
- Run `puts Rails.env` after loading the app:
4
+ Examples:
5
+ Run `puts Rails.env` after loading the app:
4
6
 
5
- <%= executable %> 'puts Rails.env'
7
+ <%= executable %> 'puts Rails.env'
6
8
 
7
- Run the Ruby file located at `path/to/filename.rb` after loading the app:
9
+ Run the Ruby file located at `path/to/filename.rb` after loading the app:
8
10
 
9
- <%= executable %> path/to/filename.rb
11
+ <%= executable %> path/to/filename.rb
10
12
 
11
- Run the Ruby script read from stdin after loading the app:
12
- <%= executable %> -
13
+ Run the Ruby script read from stdin after loading the app:
13
14
 
14
- <% unless Gem.win_platform? %>
15
- You can also use the runner command as a shebang line for your executables:
15
+ <%= executable %> -
16
+ <% unless Gem.win_platform? -%>
16
17
 
17
- #!/usr/bin/env <%= File.expand_path(executable) %>
18
+ You can also use the runner command as a shebang line for your executables:
18
19
 
19
- Product.all.each { |p| p.price *= 2 ; p.save! }
20
- <% end %>
20
+ #!/usr/bin/env <%= File.expand_path(executable) %>
21
+ Product.all.each { |p| p.price *= 2 ; p.save! }
22
+ <% end -%>
@@ -7,52 +7,64 @@ module Rails
7
7
  class RunnerCommand < Base # :nodoc:
8
8
  include EnvironmentArgument
9
9
 
10
- self.environment_desc = "The environment for the runner to operate under (test/development/production)"
11
-
12
10
  no_commands do
13
- def help
11
+ def help(command_name = nil, *)
14
12
  super
15
- say self.class.desc
13
+ if command_name == "runner"
14
+ say ""
15
+ say self.class.class_usage
16
+ end
16
17
  end
17
18
  end
18
19
 
19
- def self.banner(*)
20
- "#{super} [<'Some.ruby(code)'> | <filename.rb> | -]"
21
- end
22
-
20
+ desc "runner [<'Some.ruby(code)'> | <filename.rb> | -]",
21
+ "Run Ruby code in the context of your application"
23
22
  def perform(code_or_file = nil, *command_argv)
24
- extract_environment_option_from_argument
25
-
26
23
  unless code_or_file
27
24
  help
28
25
  exit 1
29
26
  end
30
27
 
31
- ENV["RAILS_ENV"] = options[:environment]
32
-
33
- require_application_and_environment!
28
+ boot_application!
34
29
  Rails.application.load_runner
35
30
 
36
31
  ARGV.replace(command_argv)
37
32
 
38
33
  if code_or_file == "-"
39
- eval($stdin.read, TOPLEVEL_BINDING, "stdin")
34
+ Rails.application.executor.wrap(source: "application.runner.railties") do
35
+ eval($stdin.read, TOPLEVEL_BINDING, "stdin")
36
+ end
40
37
  elsif File.exist?(code_or_file)
41
38
  expanded_file_path = File.expand_path code_or_file
42
39
  $0 = expanded_file_path
43
- Kernel.load expanded_file_path
40
+ Rails.application.executor.wrap(source: "application.runner.railties") do
41
+ Kernel.load expanded_file_path
42
+ end
44
43
  else
45
44
  begin
46
- eval(code_or_file, TOPLEVEL_BINDING, __FILE__, __LINE__)
45
+ Rails.application.executor.wrap(source: "application.runner.railties") do
46
+ eval(code_or_file, TOPLEVEL_BINDING, __FILE__, __LINE__)
47
+ end
47
48
  rescue SyntaxError, NameError => e
48
- error "Please specify a valid ruby command or the path of a script to run."
49
- error "Run '#{self.class.executable} -h' for help."
50
- error ""
51
- error e
49
+ if looks_like_a_file_path?(code_or_file)
50
+ error "The file #{code_or_file} could not be found, please check and try again."
51
+ error "Run '#{self.class.executable} -h' for help."
52
+ else
53
+ error "Please specify a valid ruby command or the path of a script to run."
54
+ error "Run '#{self.class.executable} -h' for help."
55
+ error ""
56
+ error e
57
+ end
58
+
52
59
  exit 1
53
60
  end
54
61
  end
55
62
  end
63
+
64
+ private
65
+ def looks_like_a_file_path?(code_or_file)
66
+ code_or_file.ends_with?(".rb")
67
+ end
56
68
  end
57
69
  end
58
70
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module Command
5
+ class SecretCommand < Base # :nodoc:
6
+ desc "secret", "Generate a cryptographically secure secret key (this is typically used to generate a secret for cookie sessions)."
7
+ def perform
8
+ require "securerandom"
9
+ puts SecureRandom.hex(64)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,66 +1,61 @@
1
- === ** DEPRECATED **
1
+ Description:
2
+ ** DEPRECATED **
3
+ Rails 5.2 has introduced a new `credentials` API that replaces Rails secrets.
4
+ Please use the Rails `credentials` commands instead.
5
+ Run `bin/rails credentials:help` for more information.
2
6
 
3
- Rails 5.2 has introduced a new `credentials` API that replaces Rails secrets.
4
- Please use the Rails `credentials` commands instead.
5
- Run `rails credentials:help` for more information.
7
+ The Rails `secrets` commands helps encrypting secrets to slim a production
8
+ environment's `ENV` hash. It's also useful for atomic deploys: no need to
9
+ coordinate key changes to get everything working as the keys are shipped
10
+ with the code.
6
11
 
7
- === Storing Encrypted Secrets in Source Control
12
+ Setup:
13
+ Run `<%= executable(:setup) %>` to opt in and generate the `config/secrets.yml.key`
14
+ and `config/secrets.yml.enc` files.
8
15
 
9
- The Rails `secrets` commands helps encrypting secrets to slim a production
10
- environment's `ENV` hash. It's also useful for atomic deploys: no need to
11
- coordinate key changes to get everything working as the keys are shipped
12
- with the code.
16
+ The latter contains all the keys to be encrypted while the former holds the
17
+ encryption key.
13
18
 
14
- === Setup
19
+ Don't lose the key! Put it in a password manager your team can access.
20
+ Should you lose it no one, including you, will be able to access any encrypted
21
+ secrets.
22
+ Don't commit the key! Add `config/secrets.yml.key` to your source control's
23
+ ignore file. If you use Git, Rails handles this for you.
15
24
 
16
- Run `bin/rails secrets:setup` to opt in and generate the `config/secrets.yml.key`
17
- and `config/secrets.yml.enc` files.
25
+ Rails also looks for the key in `ENV["RAILS_MASTER_KEY"]` if that's easier to
26
+ manage.
18
27
 
19
- The latter contains all the keys to be encrypted while the former holds the
20
- encryption key.
28
+ You could prepend that to your server's start command like this:
21
29
 
22
- Don't lose the key! Put it in a password manager your team can access.
23
- Should you lose it no one, including you, will be able to access any encrypted
24
- secrets.
25
- Don't commit the key! Add `config/secrets.yml.key` to your source control's
26
- ignore file. If you use Git, Rails handles this for you.
30
+ RAILS_MASTER_KEY="im-the-master-now-hahaha" bin/rails server
27
31
 
28
- Rails also looks for the key in `ENV["RAILS_MASTER_KEY"]` if that's easier to
29
- manage.
32
+ The `config/secrets.yml.enc` has much the same format as `config/secrets.yml`:
30
33
 
31
- You could prepend that to your server's start command like this:
34
+ production:
35
+ secret_key_base: so-secret-very-hidden-wow
36
+ payment_processing_gateway_key: much-safe-very-gaedwey-wow
32
37
 
33
- RAILS_MASTER_KEY="im-the-master-now-hahaha" server.start
38
+ But that's where the similarities between `secrets.yml` and `secrets.yml.enc`
39
+ end, e.g. no keys from `secrets.yml` will be moved to `secrets.yml.enc` and
40
+ be encrypted.
34
41
 
42
+ A `shared:` top level key is also supported such that any keys there is merged
43
+ into the other environments.
35
44
 
36
- The `config/secrets.yml.enc` has much the same format as `config/secrets.yml`:
45
+ Additionally, Rails won't read encrypted secrets out of the box even if you have
46
+ the key. Add this:
37
47
 
38
- production:
39
- secret_key_base: so-secret-very-hidden-wow
40
- payment_processing_gateway_key: much-safe-very-gaedwey-wow
48
+ config.read_encrypted_secrets = true
41
49
 
42
- But that's where the similarities between `secrets.yml` and `secrets.yml.enc`
43
- end, e.g. no keys from `secrets.yml` will be moved to `secrets.yml.enc` and
44
- be encrypted.
50
+ to the environment you'd like to read encrypted secrets. `<%= executable(:setup) %>`
51
+ inserts this into the production environment by default.
45
52
 
46
- A `shared:` top level key is also supported such that any keys there is merged
47
- into the other environments.
53
+ Editing Secrets:
54
+ After `<%= executable(:setup) %>`, run `<%= executable(:edit) %>`.
48
55
 
49
- Additionally, Rails won't read encrypted secrets out of the box even if you have
50
- the key. Add this:
56
+ That command opens a temporary file in `$VISUAL` or `$EDITOR` with the decrypted
57
+ contents of `config/secrets.yml.enc` to edit the encrypted secrets.
51
58
 
52
- config.read_encrypted_secrets = true
53
-
54
- to the environment you'd like to read encrypted secrets. `bin/rails secrets:setup`
55
- inserts this into the production environment by default.
56
-
57
- === Editing Secrets
58
-
59
- After `bin/rails secrets:setup`, run `bin/rails secrets:edit`.
60
-
61
- That command opens a temporary file in `$EDITOR` with the decrypted contents of
62
- `config/secrets.yml.enc` to edit the encrypted secrets.
63
-
64
- When the temporary file is next saved the contents are encrypted and written to
65
- `config/secrets.yml.enc` while the file itself is destroyed to prevent secrets
66
- from leaking.
59
+ When the temporary file is next saved the contents are encrypted and written to
60
+ `config/secrets.yml.enc` while the file itself is destroyed to prevent secrets
61
+ from leaking.
@@ -1,65 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support"
4
+ require "active_support/core_ext/string/filters"
4
5
  require "rails/secrets"
6
+ require "rails/command/helpers/editor"
5
7
 
6
8
  module Rails
7
9
  module Command
8
10
  class SecretsCommand < Rails::Command::Base # :nodoc:
9
- no_commands do
10
- def help
11
- say "Usage:\n #{self.class.banner}"
12
- say ""
13
- say self.class.desc
14
- end
15
- end
16
-
17
- def setup
18
- deprecate_in_favor_of_credentials_and_exit
19
- end
11
+ include Helpers::Editor
20
12
 
13
+ desc "edit", "**deprecated** Open the secrets in `$VISUAL` or `$EDITOR` for editing"
21
14
  def edit
22
- if ENV["EDITOR"].to_s.empty?
23
- say "No $EDITOR to open decrypted secrets in. Assign one like this:"
24
- say ""
25
- say %(EDITOR="mate --wait" rails secrets:edit)
26
- say ""
27
- say "For editors that fork and exit immediately, it's important to pass a wait flag,"
28
- say "otherwise the secrets will be saved immediately with no chance to edit."
15
+ Rails.deprecator.warn(<<~MSG.squish)
16
+ `bin/rails secrets:edit` is deprecated in favor of credentials and will be removed in Rails 7.2.
17
+ Run `bin/rails credentials:help` for more information.
18
+ MSG
29
19
 
30
- return
31
- end
32
-
33
- require_application_and_environment!
20
+ boot_application!
34
21
 
35
- Rails::Secrets.read_for_editing do |tmp_path|
36
- system("#{ENV["EDITOR"]} #{tmp_path}")
22
+ using_system_editor do
23
+ Rails::Secrets.read_for_editing { |tmp_path| system_editor(tmp_path) }
24
+ say "File encrypted and saved."
37
25
  end
38
-
39
- say "New secrets encrypted and saved."
40
- rescue Interrupt
41
- say "Aborted changing encrypted secrets: nothing saved."
42
26
  rescue Rails::Secrets::MissingKeyError => error
43
27
  say error.message
44
28
  rescue Errno::ENOENT => error
45
- if /secrets\.yml\.enc/.match?(error.message)
46
- deprecate_in_favor_of_credentials_and_exit
29
+ if error.message.include?("secrets.yml.enc")
30
+ exit 1
47
31
  else
48
32
  raise
49
33
  end
50
34
  end
51
35
 
36
+ desc "show", "**deprecated** Show the decrypted secrets"
52
37
  def show
38
+ Rails.deprecator.warn(<<~MSG.squish)
39
+ `bin/rails secrets:show` is deprecated in favor of credentials and will be removed in Rails 7.2.
40
+ Run `bin/rails credentials:help` for more information.
41
+ MSG
42
+
53
43
  say Rails::Secrets.read
54
44
  end
55
-
56
- private
57
- def deprecate_in_favor_of_credentials_and_exit
58
- say "Encrypted secrets is deprecated in favor of credentials. Run:"
59
- say "rails credentials:help"
60
-
61
- exit 1
62
- end
63
45
  end
64
46
  end
65
47
  end
@@ -3,12 +3,12 @@
3
3
  require "fileutils"
4
4
  require "action_dispatch"
5
5
  require "rails"
6
- require "active_support/core_ext/string/filters"
7
6
  require "rails/dev_caching"
8
7
  require "rails/command/environment_argument"
8
+ require "rails/rackup/server"
9
9
 
10
10
  module Rails
11
- class Server < ::Rack::Server
11
+ class Server < Rackup::Server
12
12
  class Options
13
13
  def parse!(args)
14
14
  Rails::Command::ServerCommand.new([], args).server_options
@@ -79,13 +79,13 @@ module Rails
79
79
  console.formatter = Rails.logger.formatter
80
80
  console.level = Rails.logger.level
81
81
 
82
- unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDOUT)
83
- Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
82
+ unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDERR, STDOUT)
83
+ Rails.logger.broadcast_to(console)
84
84
  end
85
85
  end
86
86
 
87
87
  def use_puma?
88
- server.to_s == "Rack::Handler::Puma"
88
+ server.to_s.end_with?("Handler::Puma")
89
89
  end
90
90
  end
91
91
 
@@ -93,30 +93,32 @@ module Rails
93
93
  class ServerCommand < Base # :nodoc:
94
94
  include EnvironmentArgument
95
95
 
96
+ RACK_HANDLER_GEMS = %w(cgi webrick scgi thin puma unicorn falcon)
96
97
  # Hard-coding a bunch of handlers here as we don't have a public way of
97
- # querying them from the Rack::Handler registry.
98
- RACK_SERVERS = %w(cgi fastcgi webrick lsws scgi thin puma unicorn falcon)
98
+ # querying them from the Rackup::Handler registry.
99
+ RACK_HANDLERS = RACK_HANDLER_GEMS + %w(fastcgi lsws)
100
+ RECOMMENDED_SERVER = "puma"
99
101
 
100
102
  DEFAULT_PORT = 3000
101
103
  DEFAULT_PIDFILE = "tmp/pids/server.pid"
102
104
 
103
105
  class_option :port, aliases: "-p", type: :numeric,
104
- desc: "Runs Rails on the specified port - defaults to 3000.", banner: :port
106
+ desc: "Run Rails on the specified port - defaults to 3000.", banner: :port
105
107
  class_option :binding, aliases: "-b", type: :string,
106
- desc: "Binds Rails to the specified IP - defaults to 'localhost' in development and '0.0.0.0' in other environments'.",
108
+ desc: "Bind Rails to the specified IP - defaults to 'localhost' in development and '0.0.0.0' in other environments'.",
107
109
  banner: :IP
108
110
  class_option :config, aliases: "-c", type: :string, default: "config.ru",
109
- desc: "Uses a custom rackup configuration.", banner: :file
111
+ desc: "Use a custom rackup configuration.", banner: :file
110
112
  class_option :daemon, aliases: "-d", type: :boolean, default: false,
111
- desc: "Runs server as a Daemon."
113
+ desc: "Run server as a Daemon."
112
114
  class_option :using, aliases: "-u", type: :string,
113
- desc: "Specifies the Rack server used to run the application (thin/puma/webrick).", banner: :name
115
+ desc: "Specify the Rack server used to run the application (thin/puma/webrick).", banner: :name
114
116
  class_option :pid, aliases: "-P", type: :string,
115
- desc: "Specifies the PID file - defaults to #{DEFAULT_PIDFILE}."
117
+ desc: "Specify the PID file - defaults to #{DEFAULT_PIDFILE}."
116
118
  class_option :dev_caching, aliases: "-C", type: :boolean, default: nil,
117
- desc: "Specifies whether to perform caching in development."
119
+ desc: "Specify whether to perform caching in development."
118
120
  class_option :restart, type: :boolean, default: nil, hide: true
119
- class_option :early_hints, type: :boolean, default: nil, desc: "Enables HTTP/2 early hints."
121
+ class_option :early_hints, type: :boolean, default: nil, desc: "Enable HTTP/2 early hints."
120
122
  class_option :log_to_stdout, type: :boolean, default: nil, optional: true,
121
123
  desc: "Whether to log to stdout. Enabled by default in development when not daemonized."
122
124
 
@@ -126,8 +128,8 @@ module Rails
126
128
  @original_options = local_options - %w( --restart )
127
129
  end
128
130
 
131
+ desc "server", "Start the Rails server"
129
132
  def perform
130
- extract_environment_option_from_argument
131
133
  set_application_directory!
132
134
  prepare_restart
133
135
 
@@ -227,7 +229,7 @@ module Rails
227
229
  end
228
230
 
229
231
  def restart_command
230
- "bin/rails server #{@original_options.join(" ")} --restart"
232
+ "#{executable} #{@original_options.join(" ")} --restart"
231
233
  end
232
234
 
233
235
  def early_hints
@@ -244,33 +246,32 @@ module Rails
244
246
  File.expand_path(options[:pid] || ENV.fetch("PIDFILE", DEFAULT_PIDFILE))
245
247
  end
246
248
 
247
- def self.banner(*)
248
- "rails server -u [thin/puma/webrick] [options]"
249
- end
250
-
251
249
  def prepare_restart
252
250
  FileUtils.rm_f(pid) if options[:restart]
253
251
  end
254
252
 
255
253
  def rack_server_suggestion(server)
256
- if server.in?(RACK_SERVERS)
254
+ if server.nil?
255
+ <<~MSG
256
+ Could not find a server gem. Maybe you need to add one to the Gemfile?
257
+
258
+ gem "#{RECOMMENDED_SERVER}"
259
+
260
+ Run `#{executable} --help` for more options.
261
+ MSG
262
+ elsif server.in?(RACK_HANDLER_GEMS)
257
263
  <<~MSG
258
264
  Could not load server "#{server}". Maybe you need to the add it to the Gemfile?
259
265
 
260
266
  gem "#{server}"
261
267
 
262
- Run `bin/rails server --help` for more options.
268
+ Run `#{executable} --help` for more options.
263
269
  MSG
264
270
  else
265
- error = CorrectableError.new("Could not find server '#{server}'.", server, RACK_SERVERS)
266
- if error.respond_to?(:detailed_message)
267
- formatted_message = error.detailed_message
268
- else
269
- formatted_message = error.message
270
- end
271
+ error = CorrectableNameError.new("Could not find server '#{server}'.", server, RACK_HANDLERS)
271
272
  <<~MSG
272
- #{formatted_message}
273
- Run `bin/rails server --help` for more options.
273
+ #{error.detailed_message}
274
+ Run `#{executable} --help` for more options.
274
275
  MSG
275
276
  end
276
277
  end
@@ -279,7 +280,7 @@ module Rails
279
280
  say <<~MSG
280
281
  => Booting #{ActiveSupport::Inflector.demodulize(server)}
281
282
  => Rails #{Rails.version} application starting in #{Rails.env} #{url}
282
- => Run `bin/rails server --help` for more startup options
283
+ => Run `#{executable} --help` for more startup options
283
284
  MSG
284
285
  end
285
286
  end
@@ -0,0 +1,14 @@
1
+ Examples:
2
+ You can run a single test by appending a line number to a filename:
3
+
4
+ <%= executable %> test/models/user_test.rb:27
5
+
6
+ You can run multiple tests with in a line range by appending the line range to a filename:
7
+
8
+ <%= executable %> test/models/user_test.rb:10-20
9
+
10
+ You can run multiple files and directories at the same time:
11
+
12
+ <%= executable %> test/controllers test/integration/login_test.rb
13
+
14
+ By default test failures and errors are reported inline during a run.
@@ -1,37 +1,79 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails/command"
4
+ require "rails/commands/rake/rake_command"
4
5
  require "rails/test_unit/runner"
5
6
  require "rails/test_unit/reporter"
6
7
 
7
8
  module Rails
8
9
  module Command
9
10
  class TestCommand < Base # :nodoc:
11
+ def self.executable(*args)
12
+ args.empty? ? Rails::TestUnitReporter.executable : super
13
+ end
14
+
10
15
  no_commands do
11
- def help
12
- say "Usage: #{Rails::TestUnitReporter.executable} [options] [files or directories]"
13
- say ""
14
- say "You can run a single test by appending a line number to a filename:"
15
- say ""
16
- say " #{Rails::TestUnitReporter.executable} test/models/user_test.rb:27"
17
- say ""
18
- say "You can run multiple files and directories at the same time:"
19
- say ""
20
- say " #{Rails::TestUnitReporter.executable} test/controllers test/integration/login_test.rb"
16
+ def help(command_name = nil, *)
17
+ super
18
+ if command_name == "test"
19
+ say ""
20
+ say self.class.class_usage
21
+ end
21
22
  say ""
22
- say "By default test failures and errors are reported inline during a run."
23
- say ""
24
-
25
23
  Minitest.run(%w(--help))
26
24
  end
27
25
  end
28
26
 
29
- def perform(*)
27
+ desc "test [PATHS...]", "Run tests except system tests"
28
+ def perform(*args)
30
29
  $LOAD_PATH << Rails::Command.root.join("test").to_s
31
30
 
32
31
  Rails::TestUnit::Runner.parse_options(args)
32
+ run_prepare_task if self.args.none?(EXACT_TEST_ARGUMENT_PATTERN)
33
33
  Rails::TestUnit::Runner.run(args)
34
34
  end
35
+
36
+ # Define Thor tasks to avoid going through Rake and booting twice when using bin/rails test:*
37
+ Rails::TestUnit::Runner::TEST_FOLDERS.each do |name|
38
+ desc name, "Run tests in test/#{name}"
39
+ define_method(name) do |*args|
40
+ perform("test/#{name}", *args)
41
+ end
42
+ end
43
+
44
+ desc "all", "Run all tests, including system tests"
45
+ def all(*args)
46
+ perform("test/**/*_test.rb", *args)
47
+ end
48
+
49
+ desc "functionals", "Run tests in test/controllers, test/mailers, and test/functional"
50
+ def functionals(*args)
51
+ perform("test/controllers", "test/mailers", "test/functional", *args)
52
+ end
53
+
54
+ desc "units", "Run tests in test/models, test/helpers, and test/unit"
55
+ def units(*args)
56
+ perform("test/models", "test/helpers", "test/unit", *args)
57
+ end
58
+
59
+ desc "system", "Run system tests only"
60
+ def system(*args)
61
+ perform("test/system", *args)
62
+ end
63
+
64
+ desc "generators", "Run tests in test/lib/generators"
65
+ def generators(*args)
66
+ perform("test/lib/generators", *args)
67
+ end
68
+
69
+ private
70
+ EXACT_TEST_ARGUMENT_PATTERN = /^-n|^--name\b|#{Rails::TestUnit::Runner::PATH_ARGUMENT_PATTERN}/
71
+
72
+ def run_prepare_task
73
+ Rails::Command::RakeCommand.perform("test:prepare", [], {})
74
+ rescue UnrecognizedCommandError => error
75
+ raise unless error.name == "test:prepare"
76
+ end
35
77
  end
36
78
  end
37
79
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/commands/routes/routes_command"
4
+
5
+ module Rails
6
+ module Command
7
+ class UnusedRoutesCommand < Rails::Command::Base # :nodoc:
8
+ hide_command!
9
+ class_option :controller, aliases: "-c", desc: "Filter by a specific controller, e.g. PostsController or Admin::PostsController."
10
+ class_option :grep, aliases: "-g", desc: "Grep routes by a specific pattern."
11
+
12
+ class RouteInfo
13
+ def initialize(route)
14
+ requirements = route.requirements
15
+ @controller_name = requirements[:controller]
16
+ @action_name = requirements[:action]
17
+ @controller_class = (@controller_name.to_s.camelize + "Controller").safe_constantize
18
+ end
19
+
20
+ def unused?
21
+ controller_class_missing? || (action_missing? && template_missing?)
22
+ end
23
+
24
+ private
25
+ def view_path(root)
26
+ File.join(root.path, @controller_name, @action_name)
27
+ end
28
+
29
+ def controller_class_missing?
30
+ @controller_name && @controller_class.nil?
31
+ end
32
+
33
+ def template_missing?
34
+ @controller_class && @controller_class.try(:view_paths).to_a.flat_map { |path| Dir["#{view_path(path)}.*"] }.none?
35
+ end
36
+
37
+ def action_missing?
38
+ @controller_class && @controller_class.instance_methods.exclude?(@action_name.to_sym)
39
+ end
40
+ end
41
+
42
+ def perform(*)
43
+ boot_application!
44
+ require "action_dispatch/routing/inspector"
45
+
46
+ say(inspector.format(formatter, routes_filter))
47
+
48
+ exit(1) if routes.any?
49
+ end
50
+
51
+ private
52
+ def inspector
53
+ ActionDispatch::Routing::RoutesInspector.new(routes)
54
+ end
55
+
56
+ def routes
57
+ @routes ||= begin
58
+ routes = Rails.application.routes.routes.select do |route|
59
+ RouteInfo.new(route).unused?
60
+ end
61
+
62
+ ActionDispatch::Journey::Routes.new(routes)
63
+ end
64
+ end
65
+
66
+ def formatter
67
+ ActionDispatch::Routing::ConsoleFormatter::Unused.new
68
+ end
69
+
70
+ def routes_filter
71
+ options.symbolize_keys.slice(:controller, :grep)
72
+ end
73
+ end
74
+ end
75
+ end