railties 6.0.0.beta2 → 6.0.2.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +150 -7
  3. data/RDOC_MAIN.rdoc +3 -3
  4. data/README.rdoc +1 -1
  5. data/lib/rails/api/task.rb +1 -0
  6. data/lib/rails/application.rb +23 -5
  7. data/lib/rails/application/bootstrap.rb +2 -10
  8. data/lib/rails/application/configuration.rb +45 -1
  9. data/lib/rails/application/default_middleware_stack.rb +1 -0
  10. data/lib/rails/application/dummy_erb_compiler.rb +18 -0
  11. data/lib/rails/application/finisher.rb +44 -1
  12. data/lib/rails/autoloaders.rb +14 -2
  13. data/lib/rails/command/base.rb +4 -0
  14. data/lib/rails/command/environment_argument.rb +7 -4
  15. data/lib/rails/commands/console/console_command.rb +6 -0
  16. data/lib/rails/commands/credentials/USAGE +1 -1
  17. data/lib/rails/commands/credentials/credentials_command.rb +17 -3
  18. data/lib/rails/commands/dbconsole/dbconsole_command.rb +19 -7
  19. data/lib/rails/commands/dev/dev_command.rb +4 -2
  20. data/lib/rails/commands/encrypted/USAGE +28 -0
  21. data/lib/rails/commands/encrypted/encrypted_command.rb +1 -0
  22. data/lib/rails/commands/initializers/initializers_command.rb +7 -0
  23. data/lib/rails/commands/notes/notes_command.rb +1 -1
  24. data/lib/rails/commands/runner/runner_command.rb +7 -3
  25. data/lib/rails/commands/server/server_command.rb +8 -6
  26. data/lib/rails/engine.rb +41 -42
  27. data/lib/rails/engine/configuration.rb +3 -2
  28. data/lib/rails/gem_version.rb +2 -2
  29. data/lib/rails/generators.rb +2 -0
  30. data/lib/rails/generators/app_base.rb +5 -5
  31. data/lib/rails/generators/app_name.rb +2 -2
  32. data/lib/rails/generators/base.rb +4 -0
  33. data/lib/rails/generators/database.rb +1 -1
  34. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt +6 -3
  35. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +8 -0
  36. data/lib/rails/generators/generated_attribute.rb +36 -10
  37. data/lib/rails/generators/named_base.rb +1 -1
  38. data/lib/rails/generators/rails/app/app_generator.rb +1 -0
  39. data/lib/rails/generators/rails/app/templates/Gemfile.tt +4 -4
  40. data/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt +8 -0
  41. data/lib/rails/generators/rails/app/templates/bin/setup.tt +3 -2
  42. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +1 -1
  43. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
  44. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +2 -0
  45. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +2 -0
  46. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +10 -4
  47. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +3 -0
  48. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt +12 -0
  49. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +3 -0
  50. data/lib/rails/generators/rails/app/templates/gitignore.tt +1 -0
  51. data/lib/rails/generators/rails/app/templates/package.json.tt +3 -3
  52. data/lib/rails/generators/rails/app/templates/public/robots.txt +1 -1
  53. data/lib/rails/generators/rails/app/templates/ruby-version.tt +1 -1
  54. data/lib/rails/generators/rails/assets/assets_generator.rb +7 -0
  55. data/lib/rails/generators/rails/db/system/change/change_generator.rb +12 -2
  56. data/lib/rails/generators/rails/plugin/plugin_generator.rb +0 -15
  57. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +1 -0
  58. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +14 -0
  59. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +1 -1
  60. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +1 -1
  61. data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +2 -2
  62. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +7 -2
  63. data/lib/rails/info.rb +1 -1
  64. data/lib/rails/mailers_controller.rb +6 -3
  65. data/lib/rails/source_annotation_extractor.rb +19 -6
  66. data/lib/rails/tasks.rb +1 -0
  67. data/lib/rails/tasks/zeitwerk.rake +66 -0
  68. metadata +18 -13
  69. data/lib/rails/generators/rails/app/templates/bin/update.tt +0 -33
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/string/inflections"
4
+ require "active_support/core_ext/array/conversions"
5
+
3
6
  module Rails
4
7
  class Application
5
8
  module Finisher
@@ -21,10 +24,50 @@ module Rails
21
24
  end
22
25
  end
23
26
 
27
+ # This will become an error if/when we remove classic mode. The plan is
28
+ # autoloaders won't be configured up to this point in the finisher, so
29
+ # constants just won't be found, raising regular NameError exceptions.
30
+ initializer :warn_if_autoloaded, before: :let_zeitwerk_take_over do
31
+ next if config.cache_classes
32
+ next if ActiveSupport::Dependencies.autoloaded_constants.empty?
33
+
34
+ autoloaded = ActiveSupport::Dependencies.autoloaded_constants
35
+ constants = "constant".pluralize(autoloaded.size)
36
+ enum = autoloaded.to_sentence
37
+ have = autoloaded.size == 1 ? "has" : "have"
38
+ these = autoloaded.size == 1 ? "This" : "These"
39
+ example = autoloaded.first
40
+ example_klass = example.constantize.class
41
+
42
+ if config.autoloader == :zeitwerk
43
+ ActiveSupport::DescendantsTracker.clear
44
+ ActiveSupport::Dependencies.clear
45
+
46
+ unload_message = "#{these} autoloaded #{constants} #{have} been unloaded."
47
+ else
48
+ unload_message = "`config.autoloader` is set to `#{config.autoloader}`. #{these} autoloaded #{constants} would have been unloaded if `config.autoloader` had been set to `:zeitwerk`."
49
+ end
50
+
51
+ ActiveSupport::Deprecation.warn(<<~WARNING)
52
+ Initialization autoloaded the #{constants} #{enum}.
53
+
54
+ Being able to do this is deprecated. Autoloading during initialization is going
55
+ to be an error condition in future versions of Rails.
56
+
57
+ Reloading does not reboot the application, and therefore code executed during
58
+ initialization does not run again. So, if you reload #{example}, for example,
59
+ the expected changes won't be reflected in that stale #{example_klass} object.
60
+
61
+ #{unload_message}
62
+
63
+ Please, check the "Autoloading and Reloading Constants" guide for solutions.
64
+ WARNING
65
+ end
66
+
24
67
  initializer :let_zeitwerk_take_over do
25
68
  if config.autoloader == :zeitwerk
26
69
  require "active_support/dependencies/zeitwerk_integration"
27
- ActiveSupport::Dependencies::ZeitwerkIntegration.take_over
70
+ ActiveSupport::Dependencies::ZeitwerkIntegration.take_over(enable_reloading: !config.cache_classes)
28
71
  end
29
72
  end
30
73
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/dependencies/zeitwerk_integration"
4
+
3
5
  module Rails
4
6
  module Autoloaders # :nodoc:
5
7
  class << self
@@ -7,13 +9,19 @@ module Rails
7
9
 
8
10
  def main
9
11
  if zeitwerk_enabled?
10
- @main ||= Zeitwerk::Loader.new.tap { |loader| loader.tag = "rails.main" }
12
+ @main ||= Zeitwerk::Loader.new.tap do |loader|
13
+ loader.tag = "rails.main"
14
+ loader.inflector = ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector
15
+ end
11
16
  end
12
17
  end
13
18
 
14
19
  def once
15
20
  if zeitwerk_enabled?
16
- @once ||= Zeitwerk::Loader.new.tap { |loader| loader.tag = "rails.once" }
21
+ @once ||= Zeitwerk::Loader.new.tap do |loader|
22
+ loader.tag = "rails.once"
23
+ loader.inflector = ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector
24
+ end
17
25
  end
18
26
  end
19
27
 
@@ -28,6 +36,10 @@ module Rails
28
36
  each { |loader| loader.logger = logger }
29
37
  end
30
38
 
39
+ def log!
40
+ each(&:log!)
41
+ end
42
+
31
43
  def zeitwerk_enabled?
32
44
  Rails.configuration.autoloader == :zeitwerk
33
45
  end
@@ -17,6 +17,10 @@ module Rails
17
17
  include Actions
18
18
 
19
19
  class << self
20
+ def exit_on_failure? # :nodoc:
21
+ false
22
+ end
23
+
20
24
  # Returns true when the app is a Rails engine.
21
25
  def engine?
22
26
  defined?(ENGINE_ROOT)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support"
4
+ require "active_support/core_ext/class/attribute"
4
5
 
5
6
  module Rails
6
7
  module Command
@@ -8,16 +9,18 @@ module Rails
8
9
  extend ActiveSupport::Concern
9
10
 
10
11
  included do
11
- class_option :environment, aliases: "-e", type: :string,
12
- desc: "Specifies the environment to run this console under (test/development/production)."
12
+ no_commands do
13
+ class_attribute :environment_desc, default: "Specifies the environment to run this #{self.command_name} under (test/development/production)."
14
+ end
15
+ class_option :environment, aliases: "-e", type: :string, desc: environment_desc
13
16
  end
14
17
 
15
18
  private
16
- def extract_environment_option_from_argument
19
+ def extract_environment_option_from_argument(default_environment: Rails::Command.environment)
17
20
  if options[:environment]
18
21
  self.options = options.merge(environment: acceptable_environment(options[:environment]))
19
22
  else
20
- self.options = options.merge(environment: Rails::Command.environment)
23
+ self.options = options.merge(environment: default_environment)
21
24
  end
22
25
  end
23
26
 
@@ -26,6 +26,12 @@ module Rails
26
26
  @options = options
27
27
 
28
28
  app.sandbox = sandbox?
29
+
30
+ if sandbox? && app.config.disable_sandbox
31
+ puts "Error: Unable to start console in sandbox mode as sandbox mode is disabled (config.disable_sandbox is true)."
32
+ exit 1
33
+ end
34
+
29
35
  app.load_console
30
36
 
31
37
  @console = app.config.console || IRB
@@ -42,7 +42,7 @@ from leaking.
42
42
  === Environment Specific Credentials
43
43
 
44
44
  The `credentials` command supports passing an `--environment` option to create an
45
- environment specific override. That override will takes precedence over the
45
+ environment specific override. That override will take precedence over the
46
46
  global `config/credentials.yml.enc` file when running in that environment. So:
47
47
 
48
48
  rails credentials:edit --environment development
@@ -2,14 +2,15 @@
2
2
 
3
3
  require "active_support"
4
4
  require "rails/command/helpers/editor"
5
+ require "rails/command/environment_argument"
5
6
 
6
7
  module Rails
7
8
  module Command
8
9
  class CredentialsCommand < Rails::Command::Base # :nodoc:
9
10
  include Helpers::Editor
11
+ include EnvironmentArgument
10
12
 
11
- class_option :environment, aliases: "-e", type: :string,
12
- desc: "Uses credentials from config/credentials/:environment.yml.enc encrypted by config/credentials/:environment.key key"
13
+ self.environment_desc = "Uses credentials from config/credentials/:environment.yml.enc encrypted by config/credentials/:environment.key key"
13
14
 
14
15
  no_commands do
15
16
  def help
@@ -20,6 +21,7 @@ module Rails
20
21
  end
21
22
 
22
23
  def edit
24
+ extract_environment_option_from_argument(default_environment: nil)
23
25
  require_application!
24
26
 
25
27
  ensure_editor_available(command: "bin/rails credentials:edit") || (return)
@@ -37,6 +39,7 @@ module Rails
37
39
  end
38
40
 
39
41
  def show
42
+ extract_environment_option_from_argument(default_environment: nil)
40
43
  require_application!
41
44
 
42
45
  say credentials.read.presence || missing_credentials_message
@@ -53,7 +56,11 @@ module Rails
53
56
  end
54
57
 
55
58
  def ensure_credentials_have_been_added
56
- encrypted_file_generator.add_encrypted_file_silently(content_path, key_path)
59
+ if options[:environment]
60
+ encrypted_file_generator.add_encrypted_file_silently(content_path, key_path)
61
+ else
62
+ credentials_generator.add_credentials_file_silently
63
+ end
57
64
  end
58
65
 
59
66
  def change_credentials_in_system_editor
@@ -93,6 +100,13 @@ module Rails
93
100
 
94
101
  Rails::Generators::EncryptedFileGenerator.new
95
102
  end
103
+
104
+ def credentials_generator
105
+ require "rails/generators"
106
+ require "rails/generators/rails/credentials/credentials_generator"
107
+
108
+ Rails::Generators::CredentialsGenerator.new
109
+ end
96
110
  end
97
111
  end
98
112
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/deprecation"
4
+ require "active_support/core_ext/string/filters"
3
5
  require "rails/command/environment_argument"
4
6
 
5
7
  module Rails
@@ -89,15 +91,15 @@ module Rails
89
91
 
90
92
  def config
91
93
  @config ||= begin
92
- # We need to check whether the user passed the connection the
94
+ # We need to check whether the user passed the database the
93
95
  # first time around to show a consistent error message to people
94
96
  # relying on 2-level database configuration.
95
- if @options["connection"] && configurations[connection].blank?
96
- raise ActiveRecord::AdapterNotSpecified, "'#{connection}' connection is not configured. Available configuration: #{configurations.inspect}"
97
- elsif configurations[environment].blank? && configurations[connection].blank?
97
+ if @options["database"] && configurations[database].blank?
98
+ raise ActiveRecord::AdapterNotSpecified, "'#{database}' database is not configured. Available configuration: #{configurations.inspect}"
99
+ elsif configurations[environment].blank? && configurations[database].blank?
98
100
  raise ActiveRecord::AdapterNotSpecified, "'#{environment}' database is not configured. Available configuration: #{configurations.inspect}"
99
101
  else
100
- configurations[connection] || configurations[environment].presence
102
+ configurations[database] || configurations[environment].presence
101
103
  end
102
104
  end
103
105
  end
@@ -106,8 +108,8 @@ module Rails
106
108
  Rails.respond_to?(:env) ? Rails.env : Rails::Command.environment
107
109
  end
108
110
 
109
- def connection
110
- @options.fetch(:connection, "primary")
111
+ def database
112
+ @options.fetch(:database, "primary")
111
113
  end
112
114
 
113
115
  private
@@ -156,12 +158,22 @@ module Rails
156
158
  class_option :connection, aliases: "-c", type: :string,
157
159
  desc: "Specifies the connection to use."
158
160
 
161
+ class_option :database, aliases: "--db", type: :string,
162
+ desc: "Specifies the database to use."
163
+
159
164
  def perform
160
165
  extract_environment_option_from_argument
161
166
 
162
167
  # RAILS_ENV needs to be set before config/application is required.
163
168
  ENV["RAILS_ENV"] = options[:environment]
164
169
 
170
+ if options["connection"]
171
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
172
+ `connection` option is deprecated and will be removed in Rails 6.1. Please use `database` option instead.
173
+ MSG
174
+ options["database"] = options["connection"]
175
+ end
176
+
165
177
  require_application_and_environment!
166
178
  Rails::DBConsole.start(options)
167
179
  end
@@ -5,8 +5,10 @@ require "rails/dev_caching"
5
5
  module Rails
6
6
  module Command
7
7
  class DevCommand < Base # :nodoc:
8
- def help
9
- say "rails dev:cache # Toggle development mode caching on/off."
8
+ no_commands do
9
+ def help
10
+ say "rails dev:cache # Toggle development mode caching on/off."
11
+ end
10
12
  end
11
13
 
12
14
  def cache
@@ -0,0 +1,28 @@
1
+ === Storing Encrypted Files in Source Control
2
+
3
+ The Rails `encrypted` commands provide access to encrypted files or configurations.
4
+ See the `Rails.application.encrypted` documentation for using them in your app.
5
+
6
+ === Encryption Keys
7
+
8
+ By default, Rails looks for the encryption key in `config/master.key` or
9
+ `ENV["RAILS_MASTER_KEY"]`, but that lookup can be overridden with `--key`:
10
+
11
+ rails encrypted:edit config/encrypted_file.yml.enc --key config/encrypted_file.key
12
+
13
+ Don't commit the key! Add it to your source control's ignore file. If you use
14
+ Git, Rails handles this for you.
15
+
16
+ === Editing Files
17
+
18
+ To edit or create an encrypted file use:
19
+
20
+ rails encrypted:edit config/encrypted_file.yml.enc
21
+
22
+ This opens a temporary file in `$EDITOR` with the decrypted contents for editing.
23
+
24
+ === Viewing Files
25
+
26
+ To print the decrypted contents of an encrypted file use:
27
+
28
+ rails encrypted:show config/encrypted_file.yml.enc
@@ -16,6 +16,7 @@ module Rails
16
16
  def help
17
17
  say "Usage:\n #{self.class.banner}"
18
18
  say ""
19
+ say self.class.desc
19
20
  end
20
21
  end
21
22
 
@@ -1,10 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rails/command/environment_argument"
4
+
3
5
  module Rails
4
6
  module Command
5
7
  class InitializersCommand < Base # :nodoc:
8
+ include EnvironmentArgument
9
+
6
10
  desc "initializers", "Print out all defined initializers in the order they are invoked by Rails."
7
11
  def perform
12
+ extract_environment_option_from_argument
13
+ ENV["RAILS_ENV"] = options[:environment]
14
+
8
15
  require_application_and_environment!
9
16
 
10
17
  Rails.application.initializers.tsort_each do |initializer|
@@ -5,7 +5,7 @@ require "rails/source_annotation_extractor"
5
5
  module Rails
6
6
  module Command
7
7
  class NotesCommand < Base # :nodoc:
8
- class_option :annotations, aliases: "-a", desc: "Filter by specific annotations, e.g. Foobar TODO", type: :array, default: %w(OPTIMIZE FIXME TODO)
8
+ class_option :annotations, aliases: "-a", desc: "Filter by specific annotations, e.g. Foobar TODO", type: :array, default: Rails::SourceAnnotationExtractor::Annotation.tags
9
9
 
10
10
  def perform(*)
11
11
  require_application_and_environment!
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rails/command/environment_argument"
4
+
3
5
  module Rails
4
6
  module Command
5
7
  class RunnerCommand < Base # :nodoc:
6
- class_option :environment, aliases: "-e", type: :string,
7
- default: Rails::Command.environment.dup,
8
- desc: "The environment for the runner to operate under (test/development/production)"
8
+ include EnvironmentArgument
9
+
10
+ self.environment_desc = "The environment for the runner to operate under (test/development/production)"
9
11
 
10
12
  no_commands do
11
13
  def help
@@ -19,6 +21,8 @@ module Rails
19
21
  end
20
22
 
21
23
  def perform(code_or_file = nil, *command_argv)
24
+ extract_environment_option_from_argument
25
+
22
26
  unless code_or_file
23
27
  help
24
28
  exit 1
@@ -6,6 +6,7 @@ require "rails"
6
6
  require "active_support/deprecation"
7
7
  require "active_support/core_ext/string/filters"
8
8
  require "rails/dev_caching"
9
+ require "rails/command/environment_argument"
9
10
 
10
11
  module Rails
11
12
  class Server < ::Rack::Server
@@ -91,6 +92,8 @@ module Rails
91
92
 
92
93
  module Command
93
94
  class ServerCommand < Base # :nodoc:
95
+ include EnvironmentArgument
96
+
94
97
  # Hard-coding a bunch of handlers here as we don't have a public way of
95
98
  # querying them from the Rack::Handler registry.
96
99
  RACK_SERVERS = %w(cgi fastcgi webrick lsws scgi thin puma unicorn)
@@ -109,8 +112,6 @@ module Rails
109
112
  desc: "Uses a custom rackup configuration.", banner: :file
110
113
  class_option :daemon, aliases: "-d", type: :boolean, default: false,
111
114
  desc: "Runs server as a Daemon."
112
- class_option :environment, aliases: "-e", type: :string,
113
- desc: "Specifies the environment to run this server under (development/test/production).", banner: :name
114
115
  class_option :using, aliases: "-u", type: :string,
115
116
  desc: "Specifies the Rack server used to run the application (thin/puma/webrick).", banner: :name
116
117
  class_option :pid, aliases: "-P", type: :string, default: DEFAULT_PID_PATH,
@@ -130,6 +131,7 @@ module Rails
130
131
  end
131
132
 
132
133
  def perform
134
+ extract_environment_option_from_argument
133
135
  set_application_directory!
134
136
  prepare_restart
135
137
 
@@ -221,8 +223,8 @@ module Rails
221
223
 
222
224
  if ENV["HOST"] && !ENV["BINDING"]
223
225
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
224
- Using the `HOST` environment to specify the IP is deprecated and will be removed in Rails 6.1.
225
- Please use `BINDING` environment instead.
226
+ Using the `HOST` environment variable to specify the IP is deprecated and will be removed in Rails 6.1.
227
+ Please use `BINDING` environment variable instead.
226
228
  MSG
227
229
 
228
230
  return ENV["HOST"]
@@ -255,7 +257,7 @@ module Rails
255
257
  end
256
258
 
257
259
  def self.banner(*)
258
- "rails server [thin/puma/webrick] [options]"
260
+ "rails server -u [thin/puma/webrick] [options]"
259
261
  end
260
262
 
261
263
  def prepare_restart
@@ -264,7 +266,7 @@ module Rails
264
266
 
265
267
  def deprecate_positional_rack_server_and_rewrite_to_option(original_options)
266
268
  if using
267
- ActiveSupport::Deprecation.warn(<<~MSG)
269
+ ActiveSupport::Deprecation.warn(<<~MSG.squish)
268
270
  Passing the Rack server name as a regular argument is deprecated
269
271
  and will be removed in the next Rails version. Please, use the -u
270
272
  option instead.