railties 6.1.0 → 7.0.0

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 (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +121 -276
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.rdoc +16 -16
  5. data/README.rdoc +1 -2
  6. data/lib/rails/all.rb +0 -1
  7. data/lib/rails/api/task.rb +1 -1
  8. data/lib/rails/app_updater.rb +3 -5
  9. data/lib/rails/application/bootstrap.rb +21 -5
  10. data/lib/rails/application/configuration.rb +79 -33
  11. data/lib/rails/application/default_middleware_stack.rb +7 -3
  12. data/lib/rails/application/finisher.rb +42 -85
  13. data/lib/rails/application/routes_reloader.rb +8 -0
  14. data/lib/rails/application.rb +32 -51
  15. data/lib/rails/application_controller.rb +2 -2
  16. data/lib/rails/autoloaders/inflector.rb +21 -0
  17. data/lib/rails/autoloaders.rb +12 -16
  18. data/lib/rails/code_statistics.rb +2 -2
  19. data/lib/rails/code_statistics_calculator.rb +10 -1
  20. data/lib/rails/command/base.rb +26 -12
  21. data/lib/rails/command/behavior.rb +1 -1
  22. data/lib/rails/command/environment_argument.rb +1 -1
  23. data/lib/rails/command.rb +11 -10
  24. data/lib/rails/commands/credentials/USAGE +4 -2
  25. data/lib/rails/commands/credentials/credentials_command/diffing.rb +26 -16
  26. data/lib/rails/commands/credentials/credentials_command.rb +8 -3
  27. data/lib/rails/commands/dbconsole/dbconsole_command.rb +10 -11
  28. data/lib/rails/commands/help/USAGE +3 -2
  29. data/lib/rails/commands/notes/notes_command.rb +2 -2
  30. data/lib/rails/commands/runner/runner_command.rb +3 -2
  31. data/lib/rails/commands/server/server_command.rb +2 -5
  32. data/lib/rails/configuration.rb +18 -23
  33. data/lib/rails/engine/configuration.rb +3 -3
  34. data/lib/rails/engine.rb +18 -24
  35. data/lib/rails/gem_version.rb +2 -2
  36. data/lib/rails/generators/actions/create_migration.rb +4 -4
  37. data/lib/rails/generators/actions.rb +35 -13
  38. data/lib/rails/generators/app_base.rb +140 -102
  39. data/lib/rails/generators/app_name.rb +1 -1
  40. data/lib/rails/generators/base.rb +9 -13
  41. data/lib/rails/generators/erb/scaffold/scaffold_generator.rb +2 -0
  42. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt +8 -8
  43. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +8 -4
  44. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +11 -28
  45. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +7 -3
  46. data/lib/rails/generators/erb/scaffold/templates/partial.html.erb.tt +17 -0
  47. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +8 -17
  48. data/lib/rails/generators/erb.rb +1 -1
  49. data/lib/rails/generators/generated_attribute.rb +45 -9
  50. data/lib/rails/generators/migration.rb +2 -6
  51. data/lib/rails/generators/model_helpers.rb +1 -1
  52. data/lib/rails/generators/named_base.rb +11 -11
  53. data/lib/rails/generators/rails/app/app_generator.rb +54 -93
  54. data/lib/rails/generators/rails/app/templates/Gemfile.tt +42 -52
  55. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +2 -2
  56. data/lib/rails/generators/rails/app/templates/app/mailers/application_mailer.rb.tt +2 -2
  57. data/lib/rails/generators/rails/app/templates/app/models/application_record.rb.tt +1 -1
  58. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +3 -9
  59. data/lib/rails/generators/rails/app/templates/bin/rails.tt +1 -4
  60. data/lib/rails/generators/rails/app/templates/bin/rake.tt +0 -3
  61. data/lib/rails/generators/rails/app/templates/bin/setup.tt +9 -14
  62. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +0 -1
  63. data/lib/rails/generators/rails/app/templates/config/boot.rb.tt +1 -1
  64. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +2 -2
  65. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +3 -3
  66. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +3 -3
  67. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +2 -2
  68. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  69. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +2 -2
  70. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +3 -3
  71. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
  72. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +5 -5
  73. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +6 -12
  74. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +11 -38
  75. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +6 -11
  76. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +1 -5
  77. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +19 -25
  78. data/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt +2 -2
  79. data/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb.tt +4 -4
  80. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +117 -0
  81. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +3 -3
  82. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +1 -1
  83. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +4 -1
  84. data/lib/rails/generators/rails/app/templates/config/storage.yml.tt +5 -5
  85. data/lib/rails/generators/rails/app/templates/db/seeds.rb.tt +2 -2
  86. data/lib/rails/generators/rails/app/templates/gitattributes.tt +0 -5
  87. data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -1
  88. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +1 -1
  89. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -2
  90. data/lib/rails/generators/rails/controller/templates/controller.rb.tt +0 -4
  91. data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
  92. data/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt +1 -1
  93. data/lib/rails/generators/rails/plugin/plugin_generator.rb +42 -24
  94. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +7 -3
  95. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +11 -20
  96. data/lib/rails/generators/rails/plugin/templates/README.md.tt +1 -1
  97. data/lib/rails/generators/rails/plugin/templates/app/mailers/%namespaced_name%/application_mailer.rb.tt +2 -2
  98. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +0 -3
  99. data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +4 -5
  100. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +0 -5
  101. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt +2 -2
  102. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/version.rb.tt +1 -1
  103. data/lib/rails/generators/rails/plugin/templates/rails/boot.rb.tt +2 -2
  104. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -7
  105. data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +0 -19
  106. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +1 -5
  107. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +6 -10
  108. data/lib/rails/generators/resource_helpers.rb +2 -2
  109. data/lib/rails/generators/test_unit/generator/templates/generator_test.rb.tt +1 -1
  110. data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +2 -2
  111. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +3 -3
  112. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +5 -5
  113. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +7 -7
  114. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +9 -11
  115. data/lib/rails/generators/testing/behaviour.rb +3 -4
  116. data/lib/rails/generators.rb +9 -22
  117. data/lib/rails/info.rb +1 -1
  118. data/lib/rails/info_controller.rb +1 -3
  119. data/lib/rails/initializable.rb +1 -1
  120. data/lib/rails/mailers_controller.rb +2 -4
  121. data/lib/rails/rack/logger.rb +0 -1
  122. data/lib/rails/railtie/configuration.rb +1 -2
  123. data/lib/rails/railtie.rb +31 -14
  124. data/lib/rails/ruby_version_check.rb +3 -3
  125. data/lib/rails/secrets.rb +4 -1
  126. data/lib/rails/source_annotation_extractor.rb +1 -1
  127. data/lib/rails/tasks/framework.rake +2 -8
  128. data/lib/rails/tasks/statistics.rake +3 -1
  129. data/lib/rails/tasks/tmp.rake +8 -1
  130. data/lib/rails/tasks/yarn.rake +10 -7
  131. data/lib/rails/tasks/zeitwerk.rake +2 -10
  132. data/lib/rails/templates/layouts/application.html.erb +15 -0
  133. data/lib/rails/templates/rails/mailers/email.html.erb +13 -11
  134. data/lib/rails/templates/rails/welcome/index.html.erb +62 -47
  135. data/lib/rails/test_unit/railtie.rb +0 -4
  136. data/lib/rails/test_unit/runner.rb +16 -9
  137. data/lib/rails/test_unit/testing.rake +4 -9
  138. data/lib/rails/welcome_controller.rb +1 -0
  139. data/lib/rails.rb +5 -0
  140. metadata +33 -36
  141. data/lib/rails/command/spellchecker.rb +0 -57
  142. data/lib/rails/generators/css/assets/assets_generator.rb +0 -15
  143. data/lib/rails/generators/css/assets/templates/stylesheet.css +0 -4
  144. data/lib/rails/generators/css/scaffold/scaffold_generator.rb +0 -18
  145. data/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js +0 -6
  146. data/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js +0 -5
  147. data/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt +0 -23
  148. data/lib/rails/generators/rails/app/templates/bin/spring.tt +0 -9
  149. data/lib/rails/generators/rails/app/templates/bin/yarn.tt +0 -18
  150. data/lib/rails/generators/rails/app/templates/config/initializers/application_controller_renderer.rb.tt +0 -8
  151. data/lib/rails/generators/rails/app/templates/config/initializers/backtrace_silencers.rb.tt +0 -8
  152. data/lib/rails/generators/rails/app/templates/config/initializers/cookies_serializer.rb.tt +0 -5
  153. data/lib/rails/generators/rails/app/templates/config/initializers/mime_types.rb.tt +0 -4
  154. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_1.rb.tt +0 -63
  155. data/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt +0 -16
  156. data/lib/rails/generators/rails/app/templates/config/spring.rb.tt +0 -6
  157. data/lib/rails/generators/rails/app/templates/package.json.tt +0 -11
  158. data/lib/rails/generators/rails/assets/USAGE +0 -16
  159. data/lib/rails/generators/rails/assets/assets_generator.rb +0 -26
  160. data/lib/rails/generators/rails/assets/templates/stylesheet.css +0 -4
  161. data/lib/rails/generators/rails/scaffold/templates/scaffold.css +0 -80
@@ -57,29 +57,6 @@ module Rails
57
57
  # 9) Build the middleware stack and run to_prepare callbacks
58
58
  # 10) Run config.before_eager_load and eager_load! if eager_load is true
59
59
  # 11) Run config.after_initialize callbacks
60
- #
61
- # == Multiple Applications
62
- #
63
- # If you decide to define multiple applications, then the first application
64
- # that is initialized will be set to +Rails.application+, unless you override
65
- # it with a different application.
66
- #
67
- # To create a new application, you can instantiate a new instance of a class
68
- # that has already been created:
69
- #
70
- # class Application < Rails::Application
71
- # end
72
- #
73
- # first_application = Application.new
74
- # second_application = Application.new(config: first_application.config)
75
- #
76
- # In the above example, the configuration from the first application was used
77
- # to initialize the second application. You can also use the +initialize_copy+
78
- # on one of the applications to create a copy of the application which shares
79
- # the configuration.
80
- #
81
- # If you decide to define Rake tasks, runners, or initializers in an
82
- # application other than +Rails.application+, then you must run them manually.
83
60
  class Application < Engine
84
61
  autoload :Bootstrap, "rails/application/bootstrap"
85
62
  autoload :Configuration, "rails/application/configuration"
@@ -246,11 +223,20 @@ module Rails
246
223
  all_configs = ActiveSupport::ConfigurationFile.parse(yaml).deep_symbolize_keys
247
224
  config, shared = all_configs[env.to_sym], all_configs[:shared]
248
225
 
226
+ if shared
227
+ config = {} if config.nil? && shared.is_a?(Hash)
228
+ if config.is_a?(Hash) && shared.is_a?(Hash)
229
+ config = shared.deep_merge(config)
230
+ elsif config.nil?
231
+ config = shared
232
+ end
233
+ end
234
+
249
235
  if config.is_a?(Hash)
250
- ActiveSupport::OrderedOptions.new.update(shared&.deep_merge(config) || config)
251
- else
252
- config || shared
236
+ config = ActiveSupport::OrderedOptions.new.update(config)
253
237
  end
238
+
239
+ config
254
240
  else
255
241
  raise "Could not load configuration. No such file - #{yaml}"
256
242
  end
@@ -259,13 +245,13 @@ module Rails
259
245
  # Stores some of the Rails initial environment parameters which
260
246
  # will be used by middlewares and engines to configure themselves.
261
247
  def env_config
262
- @app_env_config ||= begin
263
- super.merge(
248
+ @app_env_config ||= super.merge(
264
249
  "action_dispatch.parameter_filter" => config.filter_parameters,
265
250
  "action_dispatch.redirect_filter" => config.filter_redirect,
266
251
  "action_dispatch.secret_key_base" => secret_key_base,
267
252
  "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
268
253
  "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
254
+ "action_dispatch.log_rescued_responses" => config.action_dispatch.log_rescued_responses,
269
255
  "action_dispatch.logger" => Rails.logger,
270
256
  "action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner,
271
257
  "action_dispatch.key_generator" => key_generator,
@@ -288,7 +274,6 @@ module Rails
288
274
  "action_dispatch.content_security_policy_nonce_directives" => config.content_security_policy_nonce_directives,
289
275
  "action_dispatch.permissions_policy" => config.permissions_policy,
290
276
  )
291
- end
292
277
  end
293
278
 
294
279
  # If you try to define a set of Rake tasks on the instance, these will get
@@ -348,26 +333,26 @@ module Rails
348
333
  # are changing config.root inside your application definition or having a custom
349
334
  # Rails application, you will need to add lib to $LOAD_PATH on your own in case
350
335
  # you need to load files in lib/ during the application configuration as well.
351
- def self.add_lib_to_load_path!(root) #:nodoc:
336
+ def self.add_lib_to_load_path!(root) # :nodoc:
352
337
  path = File.join root, "lib"
353
338
  if File.exist?(path) && !$LOAD_PATH.include?(path)
354
339
  $LOAD_PATH.unshift(path)
355
340
  end
356
341
  end
357
342
 
358
- def require_environment! #:nodoc:
343
+ def require_environment! # :nodoc:
359
344
  environment = paths["config/environment"].existent.first
360
345
  require environment if environment
361
346
  end
362
347
 
363
- def routes_reloader #:nodoc:
348
+ def routes_reloader # :nodoc:
364
349
  @routes_reloader ||= RoutesReloader.new
365
350
  end
366
351
 
367
352
  # Returns an array of file paths appended with a hash of
368
353
  # directories-extensions suitable for ActiveSupport::FileUpdateChecker
369
354
  # API.
370
- def watchable_args #:nodoc:
355
+ def watchable_args # :nodoc:
371
356
  files, dirs = config.watchable_files.dup, config.watchable_dirs.dup
372
357
 
373
358
  ActiveSupport::Dependencies.autoload_paths.each do |path|
@@ -379,20 +364,20 @@ module Rails
379
364
 
380
365
  # Initialize the application passing the given group. By default, the
381
366
  # group is :default
382
- def initialize!(group = :default) #:nodoc:
367
+ def initialize!(group = :default) # :nodoc:
383
368
  raise "Application has been already initialized." if @initialized
384
369
  run_initializers(group, self)
385
370
  @initialized = true
386
371
  self
387
372
  end
388
373
 
389
- def initializers #:nodoc:
374
+ def initializers # :nodoc:
390
375
  Bootstrap.initializers_for(self) +
391
376
  railties_initializers(super) +
392
377
  Finisher.initializers_for(self)
393
378
  end
394
379
 
395
- def config #:nodoc:
380
+ def config # :nodoc:
396
381
  @config ||= Application::Configuration.new(self.class.find_root(self.class.called_from))
397
382
  end
398
383
 
@@ -480,11 +465,11 @@ module Rails
480
465
  )
481
466
  end
482
467
 
483
- def to_app #:nodoc:
468
+ def to_app # :nodoc:
484
469
  self
485
470
  end
486
471
 
487
- def helpers_paths #:nodoc:
472
+ def helpers_paths # :nodoc:
488
473
  config.helpers_paths
489
474
  end
490
475
 
@@ -506,17 +491,13 @@ module Rails
506
491
 
507
492
  # Eager loads the application code.
508
493
  def eager_load!
509
- if Rails.autoloaders.zeitwerk_enabled?
510
- Rails.autoloaders.each(&:eager_load)
511
- else
512
- super
513
- end
494
+ Rails.autoloaders.each(&:eager_load)
514
495
  end
515
496
 
516
497
  protected
517
498
  alias :build_middleware_stack :app
518
499
 
519
- def run_tasks_blocks(app) #:nodoc:
500
+ def run_tasks_blocks(app) # :nodoc:
520
501
  railties.each { |r| r.run_tasks_blocks(app) }
521
502
  super
522
503
  load "rails/tasks.rb"
@@ -527,28 +508,28 @@ module Rails
527
508
  end
528
509
  end
529
510
 
530
- def run_generators_blocks(app) #:nodoc:
511
+ def run_generators_blocks(app) # :nodoc:
531
512
  railties.each { |r| r.run_generators_blocks(app) }
532
513
  super
533
514
  end
534
515
 
535
- def run_runner_blocks(app) #:nodoc:
516
+ def run_runner_blocks(app) # :nodoc:
536
517
  railties.each { |r| r.run_runner_blocks(app) }
537
518
  super
538
519
  end
539
520
 
540
- def run_console_blocks(app) #:nodoc:
521
+ def run_console_blocks(app) # :nodoc:
541
522
  railties.each { |r| r.run_console_blocks(app) }
542
523
  super
543
524
  end
544
525
 
545
- def run_server_blocks(app) #:nodoc:
526
+ def run_server_blocks(app) # :nodoc:
546
527
  railties.each { |r| r.run_server_blocks(app) }
547
528
  super
548
529
  end
549
530
 
550
531
  # Returns the ordered railties for this application considering railties_order.
551
- def ordered_railties #:nodoc:
532
+ def ordered_railties # :nodoc:
552
533
  @ordered_railties ||= begin
553
534
  order = config.railties_order.map do |railtie|
554
535
  if railtie == :main_app
@@ -570,7 +551,7 @@ module Rails
570
551
  end
571
552
  end
572
553
 
573
- def railties_initializers(current) #:nodoc:
554
+ def railties_initializers(current) # :nodoc:
574
555
  initializers = []
575
556
  ordered_railties.reverse.flatten.each do |r|
576
557
  if r == self
@@ -582,7 +563,7 @@ module Rails
582
563
  initializers
583
564
  end
584
565
 
585
- def default_middleware_stack #:nodoc:
566
+ def default_middleware_stack # :nodoc:
586
567
  default_stack = DefaultMiddlewareStack.new(self, config, paths)
587
568
  default_stack.build_stack
588
569
  end
@@ -7,8 +7,8 @@ class Rails::ApplicationController < ActionController::Base # :nodoc:
7
7
  before_action :disable_content_security_policy_nonce!
8
8
 
9
9
  content_security_policy do |policy|
10
- policy.script_src :unsafe_inline
11
- policy.style_src :unsafe_inline
10
+ policy.script_src :self, :unsafe_inline
11
+ policy.style_src :self, :unsafe_inline
12
12
  end
13
13
 
14
14
  private
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector"
4
+
5
+ module Rails
6
+ module Autoloaders
7
+ module Inflector # :nodoc:
8
+ # Concurrent::Map is not needed. This is a private class, and overrides
9
+ # must be defined while the application boots.
10
+ @overrides = {}
11
+
12
+ def self.camelize(basename, _abspath)
13
+ @overrides[basename] || basename.camelize
14
+ end
15
+
16
+ def self.inflect(overrides)
17
+ @overrides.merge!(overrides)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,35 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/dependencies/zeitwerk_integration"
3
+ require "zeitwerk"
4
4
 
5
5
  module Rails
6
6
  module Autoloaders # :nodoc:
7
+ require_relative "autoloaders/inflector"
8
+
7
9
  class << self
8
10
  include Enumerable
9
11
 
10
12
  def main
11
- if zeitwerk_enabled?
12
- @main ||= Zeitwerk::Loader.new.tap do |loader|
13
- loader.tag = "rails.main"
14
- loader.inflector = ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector
15
- end
13
+ @main ||= Zeitwerk::Loader.new.tap do |loader|
14
+ loader.tag = "rails.main"
15
+ loader.inflector = Inflector
16
16
  end
17
17
  end
18
18
 
19
19
  def once
20
- if zeitwerk_enabled?
21
- @once ||= Zeitwerk::Loader.new.tap do |loader|
22
- loader.tag = "rails.once"
23
- loader.inflector = ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector
24
- end
20
+ @once ||= Zeitwerk::Loader.new.tap do |loader|
21
+ loader.tag = "rails.once"
22
+ loader.inflector = Inflector
25
23
  end
26
24
  end
27
25
 
28
26
  def each
29
- if zeitwerk_enabled?
30
- yield main
31
- yield once
32
- end
27
+ yield main
28
+ yield once
33
29
  end
34
30
 
35
31
  def logger=(logger)
@@ -41,7 +37,7 @@ module Rails
41
37
  end
42
38
 
43
39
  def zeitwerk_enabled?
44
- Rails.configuration.autoloader == :zeitwerk
40
+ true
45
41
  end
46
42
  end
47
43
  end
@@ -3,7 +3,7 @@
3
3
  require "rails/code_statistics_calculator"
4
4
  require "active_support/core_ext/enumerable"
5
5
 
6
- class CodeStatistics #:nodoc:
6
+ class CodeStatistics # :nodoc:
7
7
  TEST_TYPES = ["Controller tests",
8
8
  "Helper tests",
9
9
  "Model tests",
@@ -40,7 +40,7 @@ class CodeStatistics #:nodoc:
40
40
  Hash[@pairs.map { |pair| [pair.first, calculate_directory_statistics(pair.last)] }]
41
41
  end
42
42
 
43
- def calculate_directory_statistics(directory, pattern = /^(?!\.).*?\.(rb|js|ts|coffee|rake)$/)
43
+ def calculate_directory_statistics(directory, pattern = /^(?!\.).*?\.(rb|js|ts|css|scss|coffee|rake|erb)$/)
44
44
  stats = CodeStatisticsCalculator.new
45
45
 
46
46
  Dir.foreach(directory) do |file_name|
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CodeStatisticsCalculator #:nodoc:
3
+ class CodeStatisticsCalculator # :nodoc:
4
4
  attr_reader :lines, :code_lines, :classes, :methods
5
5
 
6
6
  PATTERNS = {
@@ -11,6 +11,15 @@ class CodeStatisticsCalculator #:nodoc:
11
11
  class: /^\s*class\s+[_A-Z]/,
12
12
  method: /^\s*def\s+[_a-z]/,
13
13
  },
14
+ erb: {
15
+ line_comment: %r{((^\s*<%#.*%>)|(<!--.*-->))},
16
+ },
17
+ css: {
18
+ line_comment: %r{^\s*/\*.*\*/},
19
+ },
20
+ scss: {
21
+ line_comment: %r{((^\s*/\*.*\*/)|(^\s*//))},
22
+ },
14
23
  js: {
15
24
  line_comment: %r{^\s*//},
16
25
  begin_block_comment: %r{^\s*/\*},
@@ -14,6 +14,24 @@ module Rails
14
14
  class Error < Thor::Error # :nodoc:
15
15
  end
16
16
 
17
+ class CorrectableError < Error # :nodoc:
18
+ attr_reader :key, :options
19
+
20
+ def initialize(message, key, options)
21
+ @key = key
22
+ @options = options
23
+ super(message)
24
+ end
25
+
26
+ if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable)
27
+ include DidYouMean::Correctable
28
+
29
+ def corrections
30
+ @corrections ||= DidYouMean::SpellChecker.new(dictionary: options).correct(key)
31
+ end
32
+ end
33
+ end
34
+
17
35
  include Actions
18
36
 
19
37
  class << self
@@ -32,7 +50,7 @@ module Rails
32
50
  if usage
33
51
  super
34
52
  else
35
- @desc ||= ERB.new(File.read(usage_path)).result(binding) if usage_path
53
+ @desc ||= ERB.new(File.read(usage_path), trim_mode: "-").result(binding) if usage_path
36
54
  end
37
55
  end
38
56
 
@@ -53,7 +71,7 @@ module Rails
53
71
  Rails::Command.hidden_commands << self
54
72
  end
55
73
 
56
- def inherited(base) #:nodoc:
74
+ def inherited(base) # :nodoc:
57
75
  super
58
76
 
59
77
  if base.name && !base.name.end_with?("Base")
@@ -86,10 +104,8 @@ module Rails
86
104
  #
87
105
  # Rails::Command::TestCommand.base_name # => 'rails'
88
106
  def base_name
89
- @base_name ||= begin
90
- if base = name.to_s.split("::").first
91
- base.underscore
92
- end
107
+ @base_name ||= if base = name.to_s.split("::").first
108
+ base.underscore
93
109
  end
94
110
  end
95
111
 
@@ -97,11 +113,9 @@ module Rails
97
113
  #
98
114
  # Rails::Command::TestCommand.command_name # => 'test'
99
115
  def command_name
100
- @command_name ||= begin
101
- if command = name.to_s.split("::").last
102
- command.chomp!("Command")
103
- command.underscore
104
- end
116
+ @command_name ||= if command = name.to_s.split("::").last
117
+ command.chomp!("Command")
118
+ command.underscore
105
119
  end
106
120
  end
107
121
 
@@ -148,7 +162,7 @@ module Rails
148
162
 
149
163
  def namespaced_commands
150
164
  commands.keys.map do |key|
151
- if command_root_namespace.match?(/(\A|\:)#{key}\z/)
165
+ if command_root_namespace.match?(/(\A|:)#{key}\z/)
152
166
  command_root_namespace
153
167
  else
154
168
  "#{command_root_namespace}:#{key}"
@@ -4,7 +4,7 @@ require "active_support"
4
4
 
5
5
  module Rails
6
6
  module Command
7
- module Behavior #:nodoc:
7
+ module Behavior # :nodoc:
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  class_methods do
@@ -5,7 +5,7 @@ require "active_support/core_ext/class/attribute"
5
5
 
6
6
  module Rails
7
7
  module Command
8
- module EnvironmentArgument #:nodoc:
8
+ module EnvironmentArgument # :nodoc:
9
9
  extend ActiveSupport::Concern
10
10
 
11
11
  included do
data/lib/rails/command.rb CHANGED
@@ -10,7 +10,6 @@ module Rails
10
10
  module Command
11
11
  extend ActiveSupport::Autoload
12
12
 
13
- autoload :Spellchecker
14
13
  autoload :Behavior
15
14
  autoload :Base
16
15
 
@@ -38,21 +37,21 @@ module Rails
38
37
  end
39
38
 
40
39
  command_name, namespace = "help", "help" if command_name.blank? || HELP_MAPPINGS.include?(command_name)
40
+ command_name, namespace, args = "application", "application", ["--help"] if rails_new_with_no_path?(args)
41
41
  command_name, namespace = "version", "version" if %w( -v --version ).include?(command_name)
42
42
 
43
- # isolate ARGV to ensure that commands depend only on the args they are given
44
- args = args.dup # args might *be* ARGV so dup before clearing
45
- old_argv = ARGV.dup
46
- ARGV.clear
43
+ original_argv = ARGV.dup
44
+ ARGV.replace(args)
47
45
 
48
46
  command = find_by_namespace(namespace, command_name)
49
47
  if command && command.all_commands[command_name]
50
48
  command.perform(command_name, args, config)
51
49
  else
50
+ args = ["--describe", full_namespace] if HELP_MAPPINGS.include?(args[0])
52
51
  find_by_namespace("rake").perform(full_namespace, args, config)
53
52
  end
54
53
  ensure
55
- ARGV.replace(old_argv)
54
+ ARGV.replace(original_argv)
56
55
  end
57
56
 
58
57
  # Rails finds namespaces similar to Thor, it only adds one rule:
@@ -60,14 +59,12 @@ module Rails
60
59
  # Command names must end with "_command.rb". This is required because Rails
61
60
  # looks in load paths and loads the command just before it's going to be used.
62
61
  #
63
- # find_by_namespace :webrat, :rails, :integration
62
+ # find_by_namespace :webrat, :integration
64
63
  #
65
64
  # Will search for the following commands:
66
65
  #
67
- # "rails:webrat", "webrat:integration", "webrat"
66
+ # "webrat", "webrat:integration", "rails:webrat", "rails:webrat:integration"
68
67
  #
69
- # Notice that "rails:commands:webrat" could be loaded as well, what
70
- # Rails looks for is the first and last parts of the namespace.
71
68
  def find_by_namespace(namespace, command_name = nil) # :nodoc:
72
69
  lookups = [ namespace ]
73
70
  lookups << "#{namespace}:#{command_name}" if command_name
@@ -96,6 +93,10 @@ module Rails
96
93
  COMMANDS_IN_USAGE = %w(generate console server test test:system dbconsole new)
97
94
  private_constant :COMMANDS_IN_USAGE
98
95
 
96
+ def rails_new_with_no_path?(args)
97
+ args == ["new"]
98
+ end
99
+
99
100
  def commands
100
101
  lookup!
101
102
 
@@ -32,8 +32,8 @@ You could prepend that to your server's start command like this:
32
32
 
33
33
  === Set up Git to Diff Credentials
34
34
 
35
- Rails provides `rails credentials:diff --enroll` to instruct Git to call `rails credentials:diff`
36
- when `git diff` is run on a credentials file.
35
+ Rails provides `bin/rails credentials:diff --enroll` to instruct Git to call
36
+ `bin/rails credentials:diff` when `git diff` is run on a credentials file.
37
37
 
38
38
  Running the command enrolls the project such that all credentials files use the
39
39
  "rails_credentials" diff driver in .gitattributes.
@@ -45,6 +45,8 @@ that isn't tracked Rails automatically ensures it's configured when running
45
45
  Otherwise each co-worker would have to run enable manually, including on each new
46
46
  repo clone.
47
47
 
48
+ To disenroll from this feature, run `bin/rails credentials:diff --disenroll`.
49
+
48
50
  === Editing Credentials
49
51
 
50
52
  This will open a temporary file in `$EDITOR` with the decrypted contents to edit
@@ -1,37 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rails::Command::CredentialsCommand::Diffing # :nodoc:
4
+ GITATTRIBUTES_ENTRY = <<~END
5
+ config/credentials/*.yml.enc diff=rails_credentials
6
+ config/credentials.yml.enc diff=rails_credentials
7
+ END
8
+
4
9
  def enroll_project_in_credentials_diffing
5
- if enrolled?
6
- true
10
+ if enrolled_in_credentials_diffing?
11
+ say "Project is already enrolled in credentials file diffing."
7
12
  else
8
- gitattributes.write(<<~end_of_template, mode: "a")
9
- config/credentials/*.yml.enc diff=rails_credentials
10
- config/credentials.yml.enc diff=rails_credentials
11
- end_of_template
13
+ gitattributes.write(GITATTRIBUTES_ENTRY, mode: "a")
12
14
 
13
- say "Project successfully enrolled!"
15
+ say "Enrolled project in credentials file diffing!"
14
16
  say "Rails ensures the rails_credentials diff driver is set when running `credentials:edit`. See `credentials:help` for more."
15
17
  end
16
18
  end
17
19
 
18
- def ensure_rails_credentials_driver_is_set
19
- set_driver if enrolled? && !driver_configured?
20
+ def disenroll_project_from_credentials_diffing
21
+ if enrolled_in_credentials_diffing?
22
+ gitattributes.write(gitattributes.read.gsub(GITATTRIBUTES_ENTRY, ""))
23
+ gitattributes.delete if gitattributes.empty?
24
+
25
+ say "Disenrolled project from credentials file diffing!"
26
+ else
27
+ say "Project is not enrolled in credentials file diffing."
28
+ end
29
+ end
30
+
31
+ def ensure_diffing_driver_is_configured
32
+ configure_diffing_driver if enrolled_in_credentials_diffing? && !diffing_driver_configured?
20
33
  end
21
34
 
22
35
  private
23
- def enrolled?
24
- gitattributes.read.match?(/config\/credentials(\/\*)?\.yml\.enc diff=rails_credentials/)
25
- rescue Errno::ENOENT
26
- false
36
+ def enrolled_in_credentials_diffing?
37
+ gitattributes.file? && gitattributes.read.include?(GITATTRIBUTES_ENTRY)
27
38
  end
28
39
 
29
- def driver_configured?
40
+ def diffing_driver_configured?
30
41
  system "git config --get diff.rails_credentials.textconv", out: File::NULL
31
42
  end
32
43
 
33
- def set_driver
34
- puts "running"
44
+ def configure_diffing_driver
35
45
  system "git config diff.rails_credentials.textconv 'bin/rails credentials:diff'"
36
46
  end
37
47
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
+ require "shellwords"
4
5
  require "active_support"
5
6
  require "rails/command/helpers/editor"
6
7
  require "rails/command/environment_argument"
@@ -32,7 +33,7 @@ module Rails
32
33
 
33
34
  ensure_encryption_key_has_been_added if credentials.key.nil?
34
35
  ensure_credentials_have_been_added
35
- ensure_rails_credentials_driver_is_set
36
+ ensure_diffing_driver_is_configured
36
37
 
37
38
  catch_editing_exceptions do
38
39
  change_credentials_in_system_editor
@@ -51,7 +52,10 @@ module Rails
51
52
  end
52
53
 
53
54
  option :enroll, type: :boolean, default: false,
54
- desc: "Enrolls project in credential file diffing with `git diff`"
55
+ desc: "Enrolls project in credentials file diffing with `git diff`"
56
+
57
+ option :disenroll, type: :boolean, default: false,
58
+ desc: "Disenrolls project from credentials file diffing"
55
59
 
56
60
  def diff(content_path = nil)
57
61
  if @content_path = content_path
@@ -61,6 +65,7 @@ module Rails
61
65
  say credentials.read.presence || credentials.content_path.read
62
66
  else
63
67
  require_application!
68
+ disenroll_project_from_credentials_diffing if options[:disenroll]
64
69
  enroll_project_in_credentials_diffing if options[:enroll]
65
70
  end
66
71
  rescue ActiveSupport::MessageEncryptor::InvalidMessage
@@ -87,7 +92,7 @@ module Rails
87
92
 
88
93
  def change_credentials_in_system_editor
89
94
  credentials.change do |tmp_path|
90
- system("#{ENV["EDITOR"]} #{tmp_path}")
95
+ system("#{ENV["EDITOR"]} #{Shellwords.escape(tmp_path)}")
91
96
  end
92
97
  end
93
98