railties 5.2.4.1 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +303 -132
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.rdoc +38 -31
  5. data/README.rdoc +2 -2
  6. data/lib/minitest/rails_plugin.rb +7 -11
  7. data/lib/rails.rb +5 -0
  8. data/lib/rails/all.rb +4 -0
  9. data/lib/rails/api/generator.rb +2 -1
  10. data/lib/rails/api/task.rb +17 -0
  11. data/lib/rails/app_loader.rb +2 -2
  12. data/lib/rails/app_updater.rb +3 -1
  13. data/lib/rails/application.rb +72 -30
  14. data/lib/rails/application/bootstrap.rb +2 -10
  15. data/lib/rails/application/configuration.rb +113 -13
  16. data/lib/rails/application/default_middleware_stack.rb +3 -0
  17. data/lib/rails/application/dummy_erb_compiler.rb +18 -0
  18. data/lib/rails/application/finisher.rb +54 -0
  19. data/lib/rails/autoloaders.rb +48 -0
  20. data/lib/rails/backtrace_cleaner.rb +5 -17
  21. data/lib/rails/code_statistics.rb +3 -3
  22. data/lib/rails/command.rb +11 -10
  23. data/lib/rails/command/base.rb +12 -8
  24. data/lib/rails/command/behavior.rb +7 -48
  25. data/lib/rails/command/environment_argument.rb +8 -15
  26. data/lib/rails/command/spellchecker.rb +58 -0
  27. data/lib/rails/commands/console/console_command.rb +6 -0
  28. data/lib/rails/commands/credentials/USAGE +19 -1
  29. data/lib/rails/commands/credentials/credentials_command.rb +52 -19
  30. data/lib/rails/commands/db/system/change/change_command.rb +20 -0
  31. data/lib/rails/commands/dbconsole/dbconsole_command.rb +20 -8
  32. data/lib/rails/commands/dev/dev_command.rb +19 -0
  33. data/lib/rails/commands/encrypted/USAGE +1 -1
  34. data/lib/rails/commands/encrypted/encrypted_command.rb +2 -2
  35. data/lib/rails/commands/help/help_command.rb +1 -1
  36. data/lib/rails/commands/initializers/initializers_command.rb +23 -0
  37. data/lib/rails/commands/new/new_command.rb +2 -2
  38. data/lib/rails/commands/notes/notes_command.rb +39 -0
  39. data/lib/rails/commands/plugin/plugin_command.rb +1 -1
  40. data/lib/rails/commands/routes/routes_command.rb +37 -0
  41. data/lib/rails/commands/runner/runner_command.rb +13 -9
  42. data/lib/rails/commands/secrets/USAGE +3 -3
  43. data/lib/rails/commands/secrets/secrets_command.rb +3 -3
  44. data/lib/rails/commands/server/server_command.rb +113 -50
  45. data/lib/rails/configuration.rb +1 -7
  46. data/lib/rails/engine.rb +24 -16
  47. data/lib/rails/engine/configuration.rb +5 -2
  48. data/lib/rails/gem_version.rb +4 -4
  49. data/lib/rails/generators.rb +11 -10
  50. data/lib/rails/generators/actions.rb +52 -39
  51. data/lib/rails/generators/app_base.rb +53 -93
  52. data/lib/rails/generators/app_name.rb +50 -0
  53. data/lib/rails/generators/base.rb +0 -4
  54. data/lib/rails/generators/database.rb +58 -0
  55. data/lib/rails/generators/erb/mailer/mailer_generator.rb +1 -1
  56. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt +6 -3
  57. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +1 -1
  58. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +9 -1
  59. data/lib/rails/generators/generated_attribute.rb +53 -27
  60. data/lib/rails/generators/migration.rb +1 -2
  61. data/lib/rails/generators/model_helpers.rb +8 -1
  62. data/lib/rails/generators/named_base.rb +1 -5
  63. data/lib/rails/generators/rails/app/app_generator.rb +37 -71
  64. data/lib/rails/generators/rails/app/templates/Gemfile.tt +7 -10
  65. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -3
  66. data/lib/rails/generators/rails/app/templates/app/{assets/javascripts/cable.js.tt → javascript/channels/consumer.js} +2 -9
  67. data/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js +5 -0
  68. data/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt +23 -0
  69. data/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt +5 -0
  70. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +4 -4
  71. data/lib/rails/generators/rails/app/templates/bin/setup.tt +7 -7
  72. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +2 -0
  73. data/lib/rails/generators/rails/app/templates/config/cable.yml.tt +1 -1
  74. data/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt +2 -2
  75. data/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt +2 -2
  76. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +2 -2
  77. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +3 -3
  78. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +3 -3
  79. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +1 -1
  80. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +4 -4
  81. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +2 -2
  82. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +6 -6
  83. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
  84. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +2 -2
  85. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +5 -2
  86. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +28 -12
  87. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +13 -6
  88. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +1 -1
  89. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +7 -0
  90. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt +45 -0
  91. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +1 -1
  92. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +4 -3
  93. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +1 -1
  94. data/lib/rails/generators/rails/app/templates/config/spring.rb.tt +6 -6
  95. data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -7
  96. data/lib/rails/generators/rails/app/templates/package.json.tt +7 -1
  97. data/lib/rails/generators/rails/app/templates/public/robots.txt +1 -1
  98. data/lib/rails/generators/rails/app/templates/ruby-version.tt +1 -1
  99. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +11 -0
  100. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +7 -0
  101. data/lib/rails/generators/rails/assets/USAGE +1 -4
  102. data/lib/rails/generators/rails/assets/assets_generator.rb +0 -1
  103. data/lib/rails/generators/rails/controller/controller_generator.rb +11 -1
  104. data/lib/rails/generators/rails/credentials/credentials_generator.rb +7 -8
  105. data/lib/rails/generators/rails/db/system/change/change_generator.rb +65 -0
  106. data/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb +4 -5
  107. data/lib/rails/generators/rails/helper/helper_generator.rb +5 -0
  108. data/lib/rails/generators/rails/plugin/plugin_generator.rb +9 -33
  109. data/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt +1 -1
  110. data/lib/rails/generators/rails/plugin/templates/app/helpers/%namespaced_name%/application_helper.rb.tt +1 -1
  111. data/lib/rails/generators/rails/plugin/templates/app/jobs/%namespaced_name%/application_job.rb.tt +1 -1
  112. data/lib/rails/generators/rails/plugin/templates/app/mailers/%namespaced_name%/application_mailer.rb.tt +1 -1
  113. data/lib/rails/generators/rails/plugin/templates/app/models/%namespaced_name%/application_record.rb.tt +1 -1
  114. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +2 -1
  115. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt +1 -1
  116. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/railtie.rb.tt +1 -1
  117. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +1 -2
  118. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +14 -0
  119. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +1 -1
  120. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +1 -1
  121. data/lib/rails/generators/resource_helpers.rb +1 -6
  122. data/lib/rails/generators/test_unit/integration/integration_generator.rb +6 -0
  123. data/lib/rails/generators/test_unit/job/job_generator.rb +5 -0
  124. data/lib/rails/generators/test_unit/mailer/mailer_generator.rb +1 -1
  125. data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +2 -2
  126. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +8 -3
  127. data/lib/rails/generators/test_unit/system/system_generator.rb +5 -0
  128. data/lib/rails/generators/testing/behaviour.rb +3 -0
  129. data/lib/rails/info.rb +3 -3
  130. data/lib/rails/info_controller.rb +1 -1
  131. data/lib/rails/mailers_controller.rb +7 -4
  132. data/lib/rails/paths.rb +19 -9
  133. data/lib/rails/railtie.rb +1 -1
  134. data/lib/rails/ruby_version_check.rb +3 -3
  135. data/lib/rails/secrets.rb +0 -1
  136. data/lib/rails/source_annotation_extractor.rb +138 -117
  137. data/lib/rails/tasks.rb +1 -0
  138. data/lib/rails/tasks/annotations.rake +9 -9
  139. data/lib/rails/tasks/dev.rake +5 -4
  140. data/lib/rails/tasks/framework.rake +5 -1
  141. data/lib/rails/tasks/initializers.rake +5 -4
  142. data/lib/rails/tasks/log.rake +0 -1
  143. data/lib/rails/tasks/routes.rake +4 -26
  144. data/lib/rails/tasks/statistics.rake +4 -0
  145. data/lib/rails/tasks/yarn.rake +1 -1
  146. data/lib/rails/tasks/zeitwerk.rake +66 -0
  147. data/lib/rails/templates/rails/welcome/index.html.erb +2 -2
  148. data/lib/rails/test_help.rb +11 -9
  149. data/lib/rails/test_unit/reporter.rb +1 -1
  150. data/lib/rails/test_unit/runner.rb +5 -5
  151. data/lib/rails/test_unit/testing.rake +1 -1
  152. metadata +34 -22
  153. data/lib/rails/generators/js/assets/assets_generator.rb +0 -15
  154. data/lib/rails/generators/js/assets/templates/javascript.js +0 -2
  155. data/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +0 -22
  156. data/lib/rails/generators/rails/app/templates/bin/bundle.tt +0 -2
  157. data/lib/rails/generators/rails/app/templates/bin/update.tt +0 -34
  158. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt +0 -38
  159. data/lib/rails/generators/rails/assets/templates/javascript.js +0 -2
@@ -1,4 +1,4 @@
1
- <%= wrap_in_modules <<-rb.strip_heredoc
1
+ <%= wrap_in_modules <<~rb
2
2
  class ApplicationController < ActionController::#{api? ? "API" : "Base"}
3
3
  #{ api? ? '# ' : '' }protect_from_forgery with: :exception
4
4
  end
@@ -1,4 +1,4 @@
1
- <%= wrap_in_modules <<-rb.strip_heredoc
1
+ <%= wrap_in_modules <<~rb
2
2
  module ApplicationHelper
3
3
  end
4
4
  rb
@@ -1,4 +1,4 @@
1
- <%= wrap_in_modules <<-rb.strip_heredoc
1
+ <%= wrap_in_modules <<~rb
2
2
  class ApplicationJob < ActiveJob::Base
3
3
  end
4
4
  rb
@@ -1,4 +1,4 @@
1
- <%= wrap_in_modules <<-rb.strip_heredoc
1
+ <%= wrap_in_modules <<~rb
2
2
  class ApplicationMailer < ActionMailer::Base
3
3
  default from: 'from@example.com'
4
4
  layout 'mailer'
@@ -1,4 +1,4 @@
1
- <%= wrap_in_modules <<-rb.strip_heredoc
1
+ <%= wrap_in_modules <<~rb
2
2
  class ApplicationRecord < ActiveRecord::Base
3
3
  self.abstract_class = true
4
4
  end
@@ -5,9 +5,10 @@ pkg/
5
5
  <% if sqlite3? -%>
6
6
  <%= dummy_path %>/db/*.sqlite3
7
7
  <%= dummy_path %>/db/*.sqlite3-journal
8
+ <%= dummy_path %>/db/*.sqlite3-*
8
9
  <% end -%>
9
10
  <%= dummy_path %>/log/*.log
10
- <% unless options[:skip_yarn] -%>
11
+ <% unless options[:skip_javascript] -%>
11
12
  <%= dummy_path %>/node_modules/
12
13
  <%= dummy_path %>/yarn-error.log
13
14
  <% end -%>
@@ -1,4 +1,4 @@
1
- <%= wrap_in_modules <<-rb.strip_heredoc
1
+ <%= wrap_in_modules <<~rb
2
2
  class Engine < ::Rails::Engine
3
3
  #{mountable? ? ' isolate_namespace ' + camelized_modules : ' '}
4
4
  #{api? ? " config.generators.api_only = true" : ' '}
@@ -1,4 +1,4 @@
1
- <%= wrap_in_modules <<-rb.strip_heredoc
1
+ <%= wrap_in_modules <<~rb
2
2
  class Railtie < ::Rails::Railtie
3
3
  end
4
4
  rb
@@ -10,8 +10,7 @@ ActiveRecord::Migrator.migrations_paths << File.expand_path('../db/migrate', __d
10
10
  <% end -%>
11
11
  require "rails/test_help"
12
12
 
13
- # Filter out Minitest backtrace while allowing backtrace from other libraries
14
- # to be shown.
13
+ # Filter out the backtrace from minitest while preserving the one from other libraries.
15
14
  Minitest.backtrace_filter = Minitest::BacktraceFilter.new
16
15
 
17
16
  <% unless engine? -%>
@@ -32,6 +32,20 @@ module Rails
32
32
  hook_for :helper, as: :scaffold do |invoked|
33
33
  invoke invoked, [ controller_name ]
34
34
  end
35
+
36
+ private
37
+
38
+ def permitted_params
39
+ attachments, others = attributes_names.partition { |name| attachments?(name) }
40
+ params = others.map { |name| ":#{name}" }
41
+ params += attachments.map { |name| "#{name}: []" }
42
+ params.join(", ")
43
+ end
44
+
45
+ def attachments?(name)
46
+ attribute = attributes.find { |attr| attr.name == name }
47
+ attribute&.attachments?
48
+ end
35
49
  end
36
50
  end
37
51
  end
@@ -54,7 +54,7 @@ class <%= controller_class_name %>Controller < ApplicationController
54
54
  <%- if attributes_names.empty? -%>
55
55
  params.fetch(:<%= singular_table_name %>, {})
56
56
  <%- else -%>
57
- params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
57
+ params.require(:<%= singular_table_name %>).permit(<%= permitted_params %>)
58
58
  <%- end -%>
59
59
  end
60
60
  end
@@ -61,7 +61,7 @@ class <%= controller_class_name %>Controller < ApplicationController
61
61
  <%- if attributes_names.empty? -%>
62
62
  params.fetch(:<%= singular_table_name %>, {})
63
63
  <%- else -%>
64
- params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
64
+ params.require(:<%= singular_table_name %>).permit(<%= permitted_params %>)
65
65
  <%- end -%>
66
66
  end
67
67
  end
@@ -25,13 +25,8 @@ module Rails
25
25
  assign_controller_names!(controller_name.pluralize)
26
26
  end
27
27
 
28
- # TODO Change this to private once we've dropped Ruby 2.2 support.
29
- # Workaround for Ruby 2.2 "private attribute?" warning.
30
- protected
31
-
32
- attr_reader :controller_name, :controller_file_name
33
-
34
28
  private
29
+ attr_reader :controller_name, :controller_file_name
35
30
 
36
31
  def controller_class_path
37
32
  if options[:model_name]
@@ -10,6 +10,12 @@ module TestUnit # :nodoc:
10
10
  def create_test_files
11
11
  template "integration_test.rb", File.join("test/integration", class_path, "#{file_name}_test.rb")
12
12
  end
13
+
14
+ private
15
+
16
+ def file_name
17
+ @_file_name ||= super.sub(/_test\z/i, "")
18
+ end
13
19
  end
14
20
  end
15
21
  end
@@ -10,6 +10,11 @@ module TestUnit # :nodoc:
10
10
  def create_test_file
11
11
  template "unit_test.rb", File.join("test/jobs", class_path, "#{file_name}_job_test.rb")
12
12
  end
13
+
14
+ private
15
+ def file_name
16
+ @_file_name ||= super.sub(/_job\z/i, "")
17
+ end
13
18
  end
14
19
  end
15
20
  end
@@ -21,7 +21,7 @@ module TestUnit # :nodoc:
21
21
 
22
22
  private
23
23
  def file_name
24
- @_file_name ||= super.gsub(/_mailer/i, "")
24
+ @_file_name ||= super.sub(/_mailer\z/i, "")
25
25
  end
26
26
  end
27
27
  end
@@ -1,4 +1,4 @@
1
- # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
1
+ # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2
2
  <% unless attributes.empty? -%>
3
3
  <% %w(one two).each do |name| %>
4
4
  <%= name %>:
@@ -7,7 +7,7 @@
7
7
  password_digest: <%%= BCrypt::Password.create('secret') %>
8
8
  <%- elsif attribute.reference? -%>
9
9
  <%= yaml_key_value(attribute.column_name.sub(/_id$/, ''), attribute.default || name) %>
10
- <%- else -%>
10
+ <%- elsif !attribute.virtual? -%>
11
11
  <%= yaml_key_value(attribute.column_name, attribute.default) %>
12
12
  <%- end -%>
13
13
  <%- if attribute.polymorphic? -%>
@@ -49,15 +49,20 @@ module TestUnit # :nodoc:
49
49
  attributes_names.map do |name|
50
50
  if %w(password password_confirmation).include?(name) && attributes.any?(&:password_digest?)
51
51
  ["#{name}", "'secret'"]
52
- else
52
+ elsif !virtual?(name)
53
53
  ["#{name}", "@#{singular_table_name}.#{name}"]
54
54
  end
55
- end.sort.to_h
55
+ end.compact.sort.to_h
56
56
  end
57
57
 
58
58
  def boolean?(name)
59
59
  attribute = attributes.find { |attr| attr.name == name }
60
- attribute && attribute.type == :boolean
60
+ attribute&.type == :boolean
61
+ end
62
+
63
+ def virtual?(name)
64
+ attribute = attributes.find { |attr| attr.name == name }
65
+ attribute&.virtual?
61
66
  end
62
67
  end
63
68
  end
@@ -14,6 +14,11 @@ module TestUnit # :nodoc:
14
14
 
15
15
  template "system_test.rb", File.join("test/system", class_path, "#{file_name.pluralize}_test.rb")
16
16
  end
17
+
18
+ private
19
+ def file_name
20
+ @_file_name ||= super.sub(/_test\z/i, "")
21
+ end
17
22
  end
18
23
  end
19
24
  end
@@ -67,6 +67,9 @@ module Rails
67
67
  def run_generator(args = default_arguments, config = {})
68
68
  capture(:stdout) do
69
69
  args += ["--skip-bundle"] unless args.include? "--dev"
70
+ args |= ["--skip-bootsnap"] unless args.include? "--no-skip-bootsnap"
71
+ args |= ["--skip-webpack-install"] unless args.include? "--no-skip-webpack-install"
72
+
70
73
  generator_class.start(args, config.reverse_merge(destination_root: destination_root))
71
74
  end
72
75
  end
@@ -41,7 +41,7 @@ module Rails
41
41
  alias inspect to_s
42
42
 
43
43
  def to_html
44
- "<table>".dup.tap do |table|
44
+ (+"<table>").tap do |table|
45
45
  properties.each do |(name, value)|
46
46
  table << %(<tr><td class="name">#{CGI.escapeHTML(name.to_s)}</td>)
47
47
  formatted_value = if value.kind_of?(Array)
@@ -63,12 +63,12 @@ module Rails
63
63
 
64
64
  # The Ruby version and platform, e.g. "2.0.0-p247 (x86_64-darwin12.4.0)".
65
65
  property "Ruby version" do
66
- "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"
66
+ RUBY_DESCRIPTION
67
67
  end
68
68
 
69
69
  # The RubyGems version, if it's installed.
70
70
  property "RubyGems version" do
71
- Gem::RubyGemsVersion
71
+ Gem::VERSION
72
72
  end
73
73
 
74
74
  property "Rack version" do
@@ -4,7 +4,7 @@ require "rails/application_controller"
4
4
  require "action_dispatch/routing/inspector"
5
5
 
6
6
  class Rails::InfoController < Rails::ApplicationController # :nodoc:
7
- prepend_view_path ActionDispatch::DebugExceptions::RESCUES_TEMPLATE_PATH
7
+ prepend_view_path ActionDispatch::DebugView::RESCUES_TEMPLATE_PATH
8
8
  layout -> { request.xhr? ? false : "application" }
9
9
 
10
10
  before_action :require_local!
@@ -3,10 +3,11 @@
3
3
  require "rails/application_controller"
4
4
 
5
5
  class Rails::MailersController < Rails::ApplicationController # :nodoc:
6
- prepend_view_path ActionDispatch::DebugExceptions::RESCUES_TEMPLATE_PATH
6
+ prepend_view_path ActionDispatch::DebugView::RESCUES_TEMPLATE_PATH
7
7
 
8
+ around_action :set_locale, only: :preview
9
+ before_action :find_preview, only: :preview
8
10
  before_action :require_local!, unless: :show_previews?
9
- before_action :find_preview, :set_locale, only: :preview
10
11
 
11
12
  helper_method :part_query, :locale_query
12
13
 
@@ -38,7 +39,7 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
38
39
  end
39
40
  else
40
41
  @part = find_preferred_part(request.format, Mime[:html], Mime[:text])
41
- render action: "email", layout: false, formats: %w[html]
42
+ render action: "email", layout: false, formats: [:html]
42
43
  end
43
44
  else
44
45
  raise AbstractController::ActionNotFound, "Email '#{@email_action}' not found in #{@preview.name}"
@@ -92,6 +93,8 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
92
93
  end
93
94
 
94
95
  def set_locale
95
- I18n.locale = params[:locale] || I18n.default_locale
96
+ I18n.with_locale(params[:locale] || I18n.default_locale) do
97
+ yield
98
+ end
96
99
  end
97
100
  end
@@ -113,10 +113,11 @@ module Rails
113
113
  attr_accessor :glob
114
114
 
115
115
  def initialize(root, current, paths, options = {})
116
- @paths = paths
117
- @current = current
118
- @root = root
119
- @glob = options[:glob]
116
+ @paths = paths
117
+ @current = current
118
+ @root = root
119
+ @glob = options[:glob]
120
+ @exclude = options[:exclude]
120
121
 
121
122
  options[:autoload_once] ? autoload_once! : skip_autoload_once!
122
123
  options[:eager_load] ? eager_load! : skip_eager_load!
@@ -189,13 +190,11 @@ module Rails
189
190
  raise "You need to set a path root" unless @root.path
190
191
  result = []
191
192
 
192
- each do |p|
193
- path = File.expand_path(p, @root.path)
193
+ each do |path|
194
+ path = File.expand_path(path, @root.path)
194
195
 
195
196
  if @glob && File.directory?(path)
196
- Dir.chdir(path) do
197
- result.concat(Dir.glob(@glob).map { |file| File.join path, file }.sort)
198
- end
197
+ result.concat files_in(path)
199
198
  else
200
199
  result << path
201
200
  end
@@ -222,6 +221,17 @@ module Rails
222
221
  end
223
222
 
224
223
  alias to_a expanded
224
+
225
+ private
226
+
227
+ def files_in(path)
228
+ Dir.chdir(path) do
229
+ files = Dir.glob(@glob)
230
+ files -= @exclude if @exclude
231
+ files.map! { |file| File.join(path, file) }
232
+ files.sort
233
+ end
234
+ end
225
235
  end
226
236
  end
227
237
  end
@@ -224,7 +224,7 @@ module Rails
224
224
  end
225
225
 
226
226
  def railtie_namespace #:nodoc:
227
- @railtie_namespace ||= self.class.parents.detect { |n| n.respond_to?(:railtie_namespace) }
227
+ @railtie_namespace ||= self.class.module_parents.detect { |n| n.respond_to?(:railtie_namespace) }
228
228
  end
229
229
 
230
230
  protected
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.2.2") && RUBY_ENGINE == "ruby"
3
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0") && RUBY_ENGINE == "ruby"
4
4
  desc = defined?(RUBY_DESCRIPTION) ? RUBY_DESCRIPTION : "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})"
5
5
  abort <<-end_message
6
6
 
7
- Rails 5 requires Ruby 2.2.2 or newer.
7
+ Rails 6 requires Ruby 2.5.0 or newer.
8
8
 
9
9
  You're running
10
10
  #{desc}
11
11
 
12
- Please upgrade to Ruby 2.2.2 or newer to continue.
12
+ Please upgrade to Ruby 2.5.0 or newer to continue.
13
13
 
14
14
  end_message
15
15
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "yaml"
4
4
  require "active_support/message_encryptor"
5
- require "active_support/core_ext/string/strip"
6
5
 
7
6
  module Rails
8
7
  # Greatly inspired by Ara T. Howard's magnificent sekrets gem. 😘
@@ -1,141 +1,162 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Implements the logic behind the rake tasks for annotations like
4
- #
5
- # rails notes
6
- # rails notes:optimize
7
- #
8
- # and friends. See <tt>rails -T notes</tt> and <tt>railties/lib/rails/tasks/annotations.rake</tt>.
9
- #
10
- # Annotation objects are triplets <tt>:line</tt>, <tt>:tag</tt>, <tt>:text</tt> that
11
- # represent the line where the annotation lives, its tag, and its text. Note
12
- # the filename is not stored.
13
- #
14
- # Annotations are looked for in comments and modulus whitespace they have to
15
- # start with the tag optionally followed by a colon. Everything up to the end
16
- # of the line (or closing ERB comment tag) is considered to be their text.
17
- class SourceAnnotationExtractor
18
- Annotation = Struct.new(:line, :tag, :text) do
19
- def self.directories
20
- @@directories ||= %w(app config db lib test) + (ENV["SOURCE_ANNOTATION_DIRECTORIES"] || "").split(",")
21
- end
3
+ require "active_support/deprecation"
22
4
 
23
- # Registers additional directories to be included
24
- # SourceAnnotationExtractor::Annotation.register_directories("spec", "another")
25
- def self.register_directories(*dirs)
26
- directories.push(*dirs)
27
- end
5
+ module Rails
6
+ # Implements the logic behind <tt>Rails::Command::NotesCommand</tt>. See <tt>rails notes --help</tt> for usage information.
7
+ #
8
+ # Annotation objects are triplets <tt>:line</tt>, <tt>:tag</tt>, <tt>:text</tt> that
9
+ # represent the line where the annotation lives, its tag, and its text. Note
10
+ # the filename is not stored.
11
+ #
12
+ # Annotations are looked for in comments and modulus whitespace they have to
13
+ # start with the tag optionally followed by a colon. Everything up to the end
14
+ # of the line (or closing ERB comment tag) is considered to be their text.
15
+ class SourceAnnotationExtractor
16
+ class Annotation < Struct.new(:line, :tag, :text)
17
+ def self.directories
18
+ @@directories ||= %w(app config db lib test)
19
+ end
28
20
 
29
- def self.extensions
30
- @@extensions ||= {}
31
- end
21
+ # Registers additional directories to be included
22
+ # Rails::SourceAnnotationExtractor::Annotation.register_directories("spec", "another")
23
+ def self.register_directories(*dirs)
24
+ directories.push(*dirs)
25
+ end
32
26
 
33
- # Registers new Annotations File Extensions
34
- # SourceAnnotationExtractor::Annotation.register_extensions("css", "scss", "sass", "less", "js") { |tag| /\/\/\s*(#{tag}):?\s*(.*)$/ }
35
- def self.register_extensions(*exts, &block)
36
- extensions[/\.(#{exts.join("|")})$/] = block
37
- end
27
+ def self.tags
28
+ @@tags ||= %w(OPTIMIZE FIXME TODO)
29
+ end
38
30
 
39
- register_extensions("builder", "rb", "rake", "yml", "yaml", "ruby") { |tag| /#\s*(#{tag}):?\s*(.*)$/ }
40
- register_extensions("css", "js") { |tag| /\/\/\s*(#{tag}):?\s*(.*)$/ }
41
- register_extensions("erb") { |tag| /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/ }
31
+ # Registers additional tags
32
+ # Rails::SourceAnnotationExtractor::Annotation.register_tags("TESTME", "DEPRECATEME")
33
+ def self.register_tags(*additional_tags)
34
+ tags.push(*additional_tags)
35
+ end
36
+
37
+ def self.extensions
38
+ @@extensions ||= {}
39
+ end
42
40
 
43
- # Returns a representation of the annotation that looks like this:
41
+ # Registers new Annotations File Extensions
42
+ # Rails::SourceAnnotationExtractor::Annotation.register_extensions("css", "scss", "sass", "less", "js") { |tag| /\/\/\s*(#{tag}):?\s*(.*)$/ }
43
+ def self.register_extensions(*exts, &block)
44
+ extensions[/\.(#{exts.join("|")})$/] = block
45
+ end
46
+
47
+ register_extensions("builder", "rb", "rake", "yml", "yaml", "ruby") { |tag| /#\s*(#{tag}):?\s*(.*)$/ }
48
+ register_extensions("css", "js") { |tag| /\/\/\s*(#{tag}):?\s*(.*)$/ }
49
+ register_extensions("erb") { |tag| /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/ }
50
+
51
+ # Returns a representation of the annotation that looks like this:
52
+ #
53
+ # [126] [TODO] This algorithm is simple and clearly correct, make it faster.
54
+ #
55
+ # If +options+ has a flag <tt>:tag</tt> the tag is shown as in the example above.
56
+ # Otherwise the string contains just line and text.
57
+ def to_s(options = {})
58
+ s = +"[#{line.to_s.rjust(options[:indent])}] "
59
+ s << "[#{tag}] " if options[:tag]
60
+ s << text
61
+ end
62
+
63
+ # Used in annotations.rake
64
+ #:nodoc:
65
+ def self.notes_task_deprecation_warning
66
+ ActiveSupport::Deprecation.warn("This rake task is deprecated and will be removed in Rails 6.1. \nRefer to `rails notes --help` for more information.\n")
67
+ puts "\n"
68
+ end
69
+ end
70
+
71
+ # Prints all annotations with tag +tag+ under the root directories +app+,
72
+ # +config+, +db+, +lib+, and +test+ (recursively).
73
+ #
74
+ # If +tag+ is <tt>nil</tt>, annotations with either default or registered tags are printed.
75
+ #
76
+ # Specific directories can be explicitly set using the <tt>:dirs</tt> key in +options+.
77
+ #
78
+ # Rails::SourceAnnotationExtractor.enumerate 'TODO|FIXME', dirs: %w(app lib), tag: true
79
+ #
80
+ # If +options+ has a <tt>:tag</tt> flag, it will be passed to each annotation's +to_s+.
44
81
  #
45
- # [126] [TODO] This algorithm is simple and clearly correct, make it faster.
82
+ # See <tt>#find_in</tt> for a list of file extensions that will be taken into account.
46
83
  #
47
- # If +options+ has a flag <tt>:tag</tt> the tag is shown as in the example above.
48
- # Otherwise the string contains just line and text.
49
- def to_s(options = {})
50
- s = "[#{line.to_s.rjust(options[:indent])}] ".dup
51
- s << "[#{tag}] " if options[:tag]
52
- s << text
84
+ # This class method is the single entry point for the `rails notes` command.
85
+ def self.enumerate(tag = nil, options = {})
86
+ tag ||= Annotation.tags.join("|")
87
+ extractor = new(tag)
88
+ dirs = options.delete(:dirs) || Annotation.directories
89
+ extractor.display(extractor.find(dirs), options)
53
90
  end
54
- end
55
91
 
56
- # Prints all annotations with tag +tag+ under the root directories +app+,
57
- # +config+, +db+, +lib+, and +test+ (recursively).
58
- #
59
- # Additional directories may be added using a comma-delimited list set using
60
- # <tt>ENV['SOURCE_ANNOTATION_DIRECTORIES']</tt>.
61
- #
62
- # Directories may also be explicitly set using the <tt>:dirs</tt> key in +options+.
63
- #
64
- # SourceAnnotationExtractor.enumerate 'TODO|FIXME', dirs: %w(app lib), tag: true
65
- #
66
- # If +options+ has a <tt>:tag</tt> flag, it will be passed to each annotation's +to_s+.
67
- #
68
- # See <tt>#find_in</tt> for a list of file extensions that will be taken into account.
69
- #
70
- # This class method is the single entry point for the rake tasks.
71
- def self.enumerate(tag, options = {})
72
- extractor = new(tag)
73
- dirs = options.delete(:dirs) || Annotation.directories
74
- extractor.display(extractor.find(dirs), options)
75
- end
76
-
77
- attr_reader :tag
78
-
79
- def initialize(tag)
80
- @tag = tag
81
- end
92
+ attr_reader :tag
82
93
 
83
- # Returns a hash that maps filenames under +dirs+ (recursively) to arrays
84
- # with their annotations.
85
- def find(dirs)
86
- dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
87
- end
94
+ def initialize(tag)
95
+ @tag = tag
96
+ end
88
97
 
89
- # Returns a hash that maps filenames under +dir+ (recursively) to arrays
90
- # with their annotations. Only files with annotations are included. Files
91
- # with extension +.builder+, +.rb+, +.rake+, +.yml+, +.yaml+, +.ruby+,
92
- # +.css+, +.js+ and +.erb+ are taken into account.
93
- def find_in(dir)
94
- results = {}
95
-
96
- Dir.glob("#{dir}/*") do |item|
97
- next if File.basename(item)[0] == ?.
98
-
99
- if File.directory?(item)
100
- results.update(find_in(item))
101
- else
102
- extension = Annotation.extensions.detect do |regexp, _block|
103
- regexp.match(item)
104
- end
98
+ # Returns a hash that maps filenames under +dirs+ (recursively) to arrays
99
+ # with their annotations.
100
+ def find(dirs)
101
+ dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
102
+ end
105
103
 
106
- if extension
107
- pattern = extension.last.call(tag)
108
- results.update(extract_annotations_from(item, pattern)) if pattern
104
+ # Returns a hash that maps filenames under +dir+ (recursively) to arrays
105
+ # with their annotations. Files with extensions registered in
106
+ # <tt>Rails::SourceAnnotationExtractor::Annotation.extensions</tt> are
107
+ # taken into account. Only files with annotations are included.
108
+ def find_in(dir)
109
+ results = {}
110
+
111
+ Dir.glob("#{dir}/*") do |item|
112
+ next if File.basename(item)[0] == ?.
113
+
114
+ if File.directory?(item)
115
+ results.update(find_in(item))
116
+ else
117
+ extension = Annotation.extensions.detect do |regexp, _block|
118
+ regexp.match(item)
119
+ end
120
+
121
+ if extension
122
+ pattern = extension.last.call(tag)
123
+ results.update(extract_annotations_from(item, pattern)) if pattern
124
+ end
109
125
  end
110
126
  end
111
- end
112
127
 
113
- results
114
- end
128
+ results
129
+ end
115
130
 
116
- # If +file+ is the filename of a file that contains annotations this method returns
117
- # a hash with a single entry that maps +file+ to an array of its annotations.
118
- # Otherwise it returns an empty hash.
119
- def extract_annotations_from(file, pattern)
120
- lineno = 0
121
- result = File.readlines(file, encoding: Encoding::BINARY).inject([]) do |list, line|
122
- lineno += 1
123
- next list unless line =~ pattern
124
- list << Annotation.new(lineno, $1, $2)
131
+ # If +file+ is the filename of a file that contains annotations this method returns
132
+ # a hash with a single entry that maps +file+ to an array of its annotations.
133
+ # Otherwise it returns an empty hash.
134
+ def extract_annotations_from(file, pattern)
135
+ lineno = 0
136
+ result = File.readlines(file, encoding: Encoding::BINARY).inject([]) do |list, line|
137
+ lineno += 1
138
+ next list unless line =~ pattern
139
+ list << Annotation.new(lineno, $1, $2)
140
+ end
141
+ result.empty? ? {} : { file => result }
125
142
  end
126
- result.empty? ? {} : { file => result }
127
- end
128
143
 
129
- # Prints the mapping from filenames to annotations in +results+ ordered by filename.
130
- # The +options+ hash is passed to each annotation's +to_s+.
131
- def display(results, options = {})
132
- options[:indent] = results.flat_map { |f, a| a.map(&:line) }.max.to_s.size
133
- results.keys.sort.each do |file|
134
- puts "#{file}:"
135
- results[file].each do |note|
136
- puts " * #{note.to_s(options)}"
144
+ # Prints the mapping from filenames to annotations in +results+ ordered by filename.
145
+ # The +options+ hash is passed to each annotation's +to_s+.
146
+ def display(results, options = {})
147
+ options[:indent] = results.flat_map { |f, a| a.map(&:line) }.max.to_s.size
148
+ results.keys.sort.each do |file|
149
+ puts "#{file}:"
150
+ results[file].each do |note|
151
+ puts " * #{note.to_s(options)}"
152
+ end
153
+ puts
137
154
  end
138
- puts
139
155
  end
140
156
  end
141
157
  end
158
+
159
+ # Remove this deprecated class in the next minor version
160
+ #:nodoc:
161
+ SourceAnnotationExtractor = ActiveSupport::Deprecation::DeprecatedConstantProxy.
162
+ new("SourceAnnotationExtractor", "Rails::SourceAnnotationExtractor")