railties 8.0.3 → 8.1.0.rc1

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +103 -205
  3. data/lib/minitest/rails_plugin.rb +48 -12
  4. data/lib/rails/application/bootstrap.rb +5 -0
  5. data/lib/rails/application/configuration.rb +31 -9
  6. data/lib/rails/application/default_middleware_stack.rb +1 -1
  7. data/lib/rails/application/finisher.rb +2 -1
  8. data/lib/rails/application/routes_reloader.rb +0 -1
  9. data/lib/rails/application.rb +1 -3
  10. data/lib/rails/code_statistics.rb +4 -1
  11. data/lib/rails/command/base.rb +0 -2
  12. data/lib/rails/command/environment_argument.rb +0 -1
  13. data/lib/rails/command.rb +1 -1
  14. data/lib/rails/commands/app/update_command.rb +1 -0
  15. data/lib/rails/commands/console/irb_console.rb +4 -4
  16. data/lib/rails/commands/credentials/credentials_command.rb +25 -5
  17. data/lib/rails/commands/encrypted/encrypted_command.rb +0 -1
  18. data/lib/rails/engine.rb +0 -1
  19. data/lib/rails/gem_version.rb +3 -3
  20. data/lib/rails/generators/actions.rb +2 -3
  21. data/lib/rails/generators/app_base.rb +49 -28
  22. data/lib/rails/generators/database.rb +1 -1
  23. data/lib/rails/generators/erb/authentication/authentication_generator.rb +2 -0
  24. data/lib/rails/generators/erb/scaffold/templates/partial.html.erb.tt +2 -2
  25. data/lib/rails/generators/generated_attribute.rb +1 -1
  26. data/lib/rails/generators/migration.rb +0 -1
  27. data/lib/rails/generators/rails/app/app_generator.rb +16 -5
  28. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +19 -15
  29. data/lib/rails/generators/rails/app/templates/Gemfile.tt +6 -1
  30. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +5 -0
  31. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +1 -0
  32. data/lib/rails/generators/rails/app/templates/bin/bundler-audit.tt +5 -0
  33. data/lib/rails/generators/rails/app/templates/bin/ci.tt +5 -0
  34. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +1 -1
  35. data/lib/rails/generators/rails/app/templates/bin/setup.tt +1 -0
  36. data/lib/rails/generators/rails/app/templates/config/bundler-audit.yml.tt +5 -0
  37. data/lib/rails/generators/rails/app/templates/config/ci.rb.tt +38 -0
  38. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +9 -1
  39. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +10 -2
  40. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
  41. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +9 -1
  42. data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +8 -5
  43. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +8 -0
  44. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +2 -2
  45. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +4 -0
  46. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_1.rb.tt +93 -0
  47. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +3 -2
  48. data/lib/rails/generators/rails/app/templates/config/storage.yml.tt +0 -7
  49. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +0 -6
  50. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +107 -21
  51. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +2 -2
  52. data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +3 -0
  53. data/lib/rails/generators/rails/app/templates/public/400.html +1 -1
  54. data/lib/rails/generators/rails/app/templates/public/404.html +2 -2
  55. data/lib/rails/generators/rails/app/templates/public/422.html +1 -1
  56. data/lib/rails/generators/rails/app/templates/public/500.html +2 -2
  57. data/lib/rails/generators/rails/authentication/authentication_generator.rb +8 -6
  58. data/lib/rails/generators/rails/authentication/templates/app/controllers/passwords_controller.rb.tt +6 -0
  59. data/lib/rails/generators/rails/authentication/templates/app/controllers/sessions_controller.rb.tt +2 -2
  60. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +3 -1
  61. data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +3 -1
  62. data/lib/rails/generators/rails/benchmark/USAGE +1 -1
  63. data/lib/rails/generators/rails/benchmark/templates/benchmark.rb.tt +0 -2
  64. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +1 -1
  65. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +4 -0
  66. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +2 -2
  67. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +1 -1
  68. data/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb +17 -5
  69. data/lib/rails/generators/rails/master_key/master_key_generator.rb +0 -12
  70. data/lib/rails/generators/rails/plugin/plugin_generator.rb +1 -0
  71. data/lib/rails/generators/rails/plugin/templates/Rakefile.tt +0 -4
  72. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +20 -9
  73. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +2 -2
  74. data/lib/rails/generators/rails/script/USAGE +1 -1
  75. data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +13 -0
  76. data/lib/rails/generators/test_unit/authentication/templates/test/controllers/passwords_controller_test.rb.tt +67 -0
  77. data/lib/rails/generators/test_unit/authentication/templates/test/controllers/sessions_controller_test.rb +33 -0
  78. data/lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt +4 -3
  79. data/lib/rails/generators/test_unit/authentication/templates/test/test_helpers/session_test_helper.rb.tt +19 -0
  80. data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +1 -1
  81. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +4 -2
  82. data/lib/rails/generators/testing/behavior.rb +0 -3
  83. data/lib/rails/generators.rb +3 -1
  84. data/lib/rails/health_controller.rb +8 -2
  85. data/lib/rails/info.rb +4 -5
  86. data/lib/rails/info_controller.rb +4 -5
  87. data/lib/rails/initializable.rb +63 -19
  88. data/lib/rails/rack/silence_request.rb +5 -2
  89. data/lib/rails/railtie/configurable.rb +0 -1
  90. data/lib/rails/railtie.rb +0 -1
  91. data/lib/rails/tasks/statistics.rake +3 -21
  92. data/lib/rails/tasks.rb +1 -3
  93. data/lib/rails/templates/rails/info/notes.html.erb +23 -0
  94. data/lib/rails/templates/rails/mailers/email.html.erb +2 -1
  95. data/lib/rails/templates/rails/welcome/index.html.erb +19 -3
  96. data/lib/rails/test_unit/reporter.rb +5 -4
  97. data/lib/rails/test_unit/runner.rb +8 -5
  98. data/lib/rails.rb +9 -2
  99. metadata +18 -15
  100. data/lib/rails/console/methods.rb +0 -7
  101. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +0 -30
  102. data/lib/rails/generators/test_unit/plugin/plugin_generator.rb +0 -15
  103. data/lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt +0 -7
  104. data/lib/rails/generators/test_unit/plugin/templates/test_helper.rb +0 -2
data/lib/rails/info.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cgi/escape"
4
- require "cgi/util" if RUBY_VERSION < "3.5"
3
+ require "active_support/core_ext/erb/util"
5
4
 
6
5
  module Rails
7
6
  # This module helps build the runtime properties that are displayed in
@@ -44,11 +43,11 @@ module Rails
44
43
  def to_html
45
44
  (+"<table>").tap do |table|
46
45
  properties.each do |(name, value)|
47
- table << %(<tr><td class="name">#{CGI.escapeHTML(name.to_s)}</td>)
46
+ table << %(<tr><td class="name">#{ERB::Util.html_escape(name.to_s)}</td>)
48
47
  formatted_value = if value.kind_of?(Array)
49
- "<ul>" + value.map { |v| "<li>#{CGI.escapeHTML(v.to_s)}</li>" }.join + "</ul>"
48
+ "<ul>" + value.map { |v| "<li>#{ERB::Util.html_escape(v.to_s)}</li>" }.join + "</ul>"
50
49
  else
51
- CGI.escapeHTML(value.to_s)
50
+ ERB::Util.html_escape(value.to_s)
52
51
  end
53
52
  table << %(<td class="value">#{formatted_value}</td></tr>)
54
53
  end
@@ -27,15 +27,14 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
27
27
  fuzzy: matching_routes(query: query, exact_match: false)
28
28
  }
29
29
  else
30
- @routes_inspector = ActionDispatch::Routing::RoutesInspector.new(_routes.routes)
30
+ @routes_inspector = ActionDispatch::Routing::RoutesInspector.new(Rails.application.routes.routes)
31
31
  @page_title = "Routes"
32
32
  end
33
33
  end
34
34
 
35
35
  def notes
36
- @annotations = Rails::SourceAnnotationExtractor.new(
37
- Rails::SourceAnnotationExtractor::Annotation.tags.join("|")
38
- ).find(
36
+ tags = params[:tag].presence || Rails::SourceAnnotationExtractor::Annotation.tags.join("|")
37
+ @annotations = Rails::SourceAnnotationExtractor.new(tags).find(
39
38
  Rails::SourceAnnotationExtractor::Annotation.directories
40
39
  )
41
40
  end
@@ -47,7 +46,7 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
47
46
  normalized_path = ("/" + query).squeeze("/")
48
47
  query_without_url_or_path_suffix = query.gsub(/(\w)(_path$)/, '\1').gsub(/(\w)(_url$)/, '\1')
49
48
 
50
- _routes.routes.filter_map do |route|
49
+ Rails.application.routes.routes.filter_map do |route|
51
50
  route_wrapper = ActionDispatch::Routing::RouteWrapper.new(route)
52
51
 
53
52
  if exact_match
@@ -9,23 +9,15 @@ module Rails
9
9
  end
10
10
 
11
11
  class Initializer
12
- attr_reader :name, :block
12
+ attr_reader :name, :block, :before, :after
13
13
 
14
- def initialize(name, context, options, &block)
15
- options[:group] ||= :default
16
- @name, @context, @options, @block = name, context, options, block
17
- end
18
-
19
- def before
20
- @options[:before]
21
- end
22
-
23
- def after
24
- @options[:after]
14
+ def initialize(name, context, before:, after:, group: nil, &block)
15
+ @group = group || :default
16
+ @name, @before, @after, @context, @block = name, before, after, context, block
25
17
  end
26
18
 
27
19
  def belongs_to?(group)
28
- @options[:group] == group || @options[:group] == :all
20
+ @group == group || @group == :all
29
21
  end
30
22
 
31
23
  def run(*args)
@@ -34,7 +26,7 @@ module Rails
34
26
 
35
27
  def bind(context)
36
28
  return self if @context
37
- Initializer.new(@name, context, @options, &block)
29
+ Initializer.new(@name, context, before:, after:, group: @group, &block)
38
30
  end
39
31
 
40
32
  def context_class
@@ -42,16 +34,66 @@ module Rails
42
34
  end
43
35
  end
44
36
 
45
- class Collection < Array
37
+ class Collection
38
+ include Enumerable
46
39
  include TSort
47
40
 
41
+ delegate_missing_to :@collection
42
+
43
+ def initialize(initializers = nil)
44
+ @order = Hash.new { |hash, key| hash[key] = Set.new }
45
+ @resolve = Hash.new { |hash, key| hash[key] = Set.new }
46
+ @collection = []
47
+ concat(initializers) if initializers
48
+ end
49
+
50
+ def to_a
51
+ @collection
52
+ end
53
+
54
+ def last
55
+ @collection.last
56
+ end
57
+
58
+ def each(&block)
59
+ @collection.each(&block)
60
+ end
61
+
48
62
  alias :tsort_each_node :each
49
63
  def tsort_each_child(initializer, &block)
50
- select { |i| i.before == initializer.name || i.name == initializer.after }.each(&block)
64
+ @order[initializer.name].each do |name|
65
+ @resolve[name].each(&block)
66
+ end
51
67
  end
52
68
 
53
69
  def +(other)
54
- Collection.new(to_a + other.to_a)
70
+ dup.concat(other.to_a)
71
+ end
72
+
73
+ def <<(initializer)
74
+ @collection << initializer
75
+ @order[initializer.before] << initializer.name if initializer.before
76
+ @order[initializer.name] << initializer.after if initializer.after
77
+ @resolve[initializer.name] << initializer
78
+ self
79
+ end
80
+
81
+ def push(*initializers)
82
+ initializers.each(&method(:<<))
83
+ self
84
+ end
85
+
86
+ alias_method(:append, :push)
87
+
88
+ def concat(*initializer_collections)
89
+ initializer_collections.each do |initializers|
90
+ initializers.each(&method(:<<))
91
+ end
92
+ self
93
+ end
94
+
95
+ def has?(name)
96
+ @resolve.key?(name)
55
97
  end
56
98
  end
57
99
 
@@ -87,8 +129,10 @@ module Rails
87
129
 
88
130
  def initializer(name, opts = {}, &blk)
89
131
  raise ArgumentError, "A block must be passed when defining an initializer" unless blk
90
- opts[:after] ||= initializers.last.name unless initializers.empty? || initializers.find { |i| i.name == opts[:before] }
91
- initializers << Initializer.new(name, nil, opts, &blk)
132
+ opts[:after] ||= initializers.last&.name unless initializers.has?(opts[:before])
133
+ initializers << Initializer.new(
134
+ name, nil, before: opts[:before], after: opts[:after], group: opts[:group], &blk
135
+ )
92
136
  end
93
137
  end
94
138
  end
@@ -10,11 +10,14 @@ module Rails
10
10
  # This is useful for preventing recurring requests like health checks from clogging the logging.
11
11
  # This middleware is used to do just that against the path /up in production by default.
12
12
  #
13
- # Example:
13
+ # Examples:
14
14
  #
15
15
  # config.middleware.insert_before \
16
16
  # Rails::Rack::Logger, Rails::Rack::SilenceRequest, path: "/up"
17
17
  #
18
+ # config.middleware.insert_before \
19
+ # Rails::Rack::Logger, Rails::Rack::SilenceRequest, path: /test$/
20
+ #
18
21
  # This middleware can also be configured using `config.silence_healthcheck_path = "/up"` in Rails.
19
22
  class SilenceRequest
20
23
  def initialize(app, path:)
@@ -22,7 +25,7 @@ module Rails
22
25
  end
23
26
 
24
27
  def call(env)
25
- if env["PATH_INFO"] == @path
28
+ if @path === env["PATH_INFO"]
26
29
  Rails.logger.silence { @app.call(env) }
27
30
  else
28
31
  @app.call(env)
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/concern"
4
3
 
5
4
  module Rails
6
5
  class Railtie
data/lib/rails/railtie.rb CHANGED
@@ -4,7 +4,6 @@ require "rails/initializable"
4
4
  require "active_support/descendants_tracker"
5
5
  require "active_support/inflector"
6
6
  require "active_support/core_ext/module/introspection"
7
- require "active_support/core_ext/module/delegation"
8
7
 
9
8
  module Rails
10
9
  # +Rails::Railtie+ is the core of the \Rails framework and provides
@@ -1,23 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rails/code_statistics"
4
- STATS_DIRECTORIES = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(
5
- Rails::CodeStatistics::DIRECTORIES,
6
- "`STATS_DIRECTORIES` is deprecated and will be removed in Rails 8.1! Use `Rails::CodeStatistics.register_directory('My Directory', 'path/to/dir)` instead.",
7
- Rails.deprecator
8
- )
9
-
10
- desc "Report code statistics (KLOCs, etc) from the application or engine"
11
- task :stats do
12
- require "rails/code_statistics"
13
- stat_directories = STATS_DIRECTORIES.collect do |name, dir|
14
- [ name, "#{File.dirname(Rake.application.rakefile_location)}/#{dir}" ]
15
- end.select { |name, dir| File.directory?(dir) }
16
-
17
- $stderr.puts Rails.deprecator.warn(<<~MSG, caller_locations(0..1))
18
- `bin/rake stats` has been deprecated and will be removed in Rails 8.1.
19
- Please use `bin/rails stats` as Rails command instead.\n
20
- MSG
21
-
22
- Rails::CodeStatistics.new(*stat_directories).to_s
23
- end
3
+ Rails.deprecator.warn <<~TEXT
4
+ rails/tasks/statistics.rake is deprecated and will be removed in Rails 8.2 without replacement.
5
+ TEXT
data/lib/rails/tasks.rb CHANGED
@@ -10,8 +10,6 @@ require "rake"
10
10
  tmp
11
11
  yarn
12
12
  zeitwerk
13
- ).tap { |arr|
14
- arr << "statistics" if Rake.application.current_scope.empty?
15
- }.each do |task|
13
+ ).each do |task|
16
14
  load "rails/tasks/#{task}.rake"
17
15
  end
@@ -33,12 +33,35 @@
33
33
  background: #282828;
34
34
  }
35
35
  }
36
+
37
+ .filter {
38
+ display: flex;
39
+ width: 100%;
40
+ justify-content: flex-end;
41
+ align-items: center;
42
+ }
43
+
44
+ .filter label[for="tag"] {
45
+ margin-right: 10px;
46
+ }
47
+
48
+ .filter select[name="tag"] {
49
+ border-radius: 8px;
50
+ padding: 0.25em;
51
+ }
36
52
  </style>
37
53
 
38
54
  <h2>
39
55
  Notes
40
56
  </h2>
41
57
 
58
+ <div class="filter">
59
+ <%= form_tag("/rails/info/notes", method: :get) do %>
60
+ <%= label_tag :tag, "Filter by Tag:" %>
61
+ <%= select_tag(:tag, options_for_select(Rails::SourceAnnotationExtractor::Annotation.tags, params[:tag]), { include_blank: "All", onchange: "this.form.submit();" }) %>
62
+ <% end %>
63
+ </div>
64
+
42
65
  <table id="route_table" class="table">
43
66
  <thead>
44
67
  <th>File Name</th>
@@ -9,6 +9,8 @@
9
9
 
10
10
  body {
11
11
  margin: 0;
12
+ display: flex;
13
+ flex-direction: column;
12
14
  }
13
15
 
14
16
  header {
@@ -18,7 +20,6 @@
18
20
  background: white;
19
21
  font: 12px "Lucida Grande", sans-serif;
20
22
  border-bottom: 1px solid #dedede;
21
- overflow: hidden;
22
23
  }
23
24
 
24
25
  dl {
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="en">
3
3
  <head>
4
4
  <title>Ruby on Rails <%= Rails.version %></title>
5
5
  <meta charset="utf-8">
@@ -35,6 +35,14 @@
35
35
  text-align: center;
36
36
  }
37
37
 
38
+ @media (prefers-color-scheme: dark) {
39
+ body {
40
+ background-color: #1a1a1a;
41
+ background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjEwMjQiIHZpZXdCb3g9IjAgMCAxNDQwIDEwMjQiIHdpZHRoPSIxNDQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Im0xNDQwIDUxMC4wMDA2NDh2LTUxMC4wMDA2NDhoLTE0NDB2Mzg0LjAwMDY0OGM0MTcuMzExOTM5IDEzMS4xNDIxNzkgODkxIDE3MS41MTMgMTQ0MCAxMjZ6IiBmaWxsPSIjMzMzIi8+PC9zdmc+);
42
+ color: #e0e0e0;
43
+ }
44
+ }
45
+
38
46
  nav {
39
47
  font-size: 0;
40
48
  height: 20vw;
@@ -48,7 +56,7 @@
48
56
 
49
57
  nav a {
50
58
  background: #D30001;
51
- border-radius: 100%;
59
+ border-radius: 50%;
52
60
  display: flex;
53
61
  transition: background 0.25s cubic-bezier(0.33, 1, 0.68, 1);
54
62
  filter: drop-shadow(0 20px 13px rgb(0 0 0 / 0.03)) drop-shadow(0 8px 5px rgb(0 0 0 / 0.08));
@@ -58,11 +66,19 @@
58
66
  background: #261B23;
59
67
  }
60
68
 
69
+ @media (prefers-color-scheme: dark) {
70
+ nav a {
71
+ background: #D30001;
72
+ filter: drop-shadow(0 20px 13px rgb(255 255 255 / 0.03)) drop-shadow(0 8px 5px rgb(255 255 255 / 0.08));
73
+ }
74
+ }
75
+
61
76
  nav a img {
62
77
  height: auto;
63
78
  max-width: 100%;
64
79
  width: 100%;
65
80
  cursor: pointer;
81
+ border-radius: 50%;
66
82
  }
67
83
 
68
84
  ul {
@@ -79,7 +95,7 @@
79
95
  <body>
80
96
  <nav>
81
97
  <a href="https://rubyonrails.org" target="_blank">
82
- <img alt="" src="data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjExMiIgdmlld0JveD0iMCAwIDExMiAxMTIiIHdpZHRoPSIxMTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTEwMC4wODIzNTcgNDguOTk5NTQwM3Y0LjExMzUwMzRoLTcuMzAwMzM4OHYxLjg5ODU0aDMuNjg0MDcxN2MxLjk3MjUwOTEgMCA0LjA3MjUzNDEgMS40NjY0MzExIDQuMTk3OTk3MSAzLjk2NjUxMjRsLjAwNTkxMy4yMzczOTc3djEuNTgyMTE2N2MtLjA4NzgyNCAzLjAwNzk1OS0yLjU0MzEyMTEgNC4xMzkwMDE4LTQuMDcxNTM4OSA0LjIwMTE3NzNsLS4xMzIzNzEyLjAwMjczMjhoLTcuMzkwNzQ1MXYtNC4wOTA5MDE4bDcuNDgxMTUxOC0uMDIyNjAxNnYtMS45ODg5NDY3aC0zLjQ4MDY1NjdjLTEuNzc1MjU4MyAwLTQuMDgxODMyMS0xLjMzODkxNTMtNC4yMTk5OTQyLTMuOTU0OTIwMWwtLjAwNjUxNzYtLjI0ODk5di0xLjQyMzkwNWMwLTIuNjk4MjQwMiAyLjI3ODIxMjktNC4xODI4NTMgNC4wNjU0NjQtNC4yNjc4NDkxbC4xNjEwNDc4LS4wMDM4NjZ6bS0xOC42OTE1NzkgMHYxMS44NjU4NzUyaDYuMTcwMjU1MXY0LjEzNjEwNTFoLTEwLjczNTc5MTl2LTE2LjAwMTk4MDN6bS02LjQ0MTQ3NTEgMHYxNi4wMDE5ODAzaC00LjU4ODEzODV2LTE2LjAwMTk4MDN6bS0xNS4yMTA5MjIgMGg0LjQwNzMyNTFsLjE4NzcyNC4wMDY2ODEyYy4wMzM4NjA5LjAwMjI3MzUuMDY4OTQ1Ny4wMDUxNDk5LjEwNTE2MDEuMDA4NjY0M2wuMjMwMDg3NS4wMjkwMTc4YzEuMjkxMzgyOS4xOTg1NDc2IDMuNTQ2MzgxNiAxLjEyMTM4MTYgMy42NzUxNzA4IDMuOTA2ODU4N2wuMDA1NzY3Ny4yNTI2ODgxdjExLjc5ODA3MDJoLTQuMjcxNzE1MXYtMi44MjUyMDg0aC00LjEzNjEwNTF2Mi44MjUyMDg0aC00LjQwNzMyNTF2LTExLjc5ODA3MDJjMC0xLjMxODQzMDYgMS4wMDQwODI2LTQuMDQ2ODQ5NSAzLjk0Njg5OS00LjE5NzQxMXptLTE5LjczOTg1MTktLjAwMjc1ODEgOC41ODAxODU3LjAwMDU3NDkuMjM4OTIzNC4wMzY3NDYyLjE0Nzk0NTkuMDI5NDE3LjI3NDExNjEuMDY1MzU4Mi4yMTI1MTk4LjA1OTkwNjguMjMyMzIyNS4wNzQ3MTgyYy4wNDAxNzkzLjAxMzc3MDQuMDgxMDQwMi4wMjgyMjAxLjEyMjUxMS4wNDMzODA0bC4yNTU1NjkxLjA5OTczNzYuMjY2NzYxOC4xMTgyODUyYzEuMzU2MDUxNS42NDAyODY2IDMuMDAyNjg1NSAyLjAzMjE1ODMgMy4wMDI2ODU1IDUuMDE2Mjk0IDAgMy4xODMwNzgxLTEuNTQ2NTI0MSA0LjUwMTQ4OTktMi42OTg4MzYyIDUuMDQyMDQ3N2wtLjIxMDk2NTEuMDkyNTA0NS0uMTk4ODgyOC4wNzU4NjU1LS4xODM5NTc3LjA2MDgxODYtLjE2NjE4OTguMDQ3MzYzNi0uMjA5NzUwOC4wNDkzMDAxLS4yNTk2NDkzLjA0MTgzNjMgNS4wMDU2ODk1IDUuMDUwNTgzNmgtNi4zNzQ5NTg5bC0zLjcyNjIwODMtMy44NjA4OTA2djMuODYwODkwNmgtNC4zMDk4MzE0em0yMi4wMDcwNjAzLTMuMDg2OTE5My40NDQ5OTE3LjQyMjY4MDctLjI0Mjk2OC4xNzc5ODgxLS4zNDgyMzMxLjI2OTMzNjUtLjE5OTg1NzMuMTYyOTIwNGMtNS4yMzk4OTY3LTMuODc0NTcxNS05LjY0NzY0NTQtNS40MjIxNDA5LTEzLjE5NzExOS01LjgxNTM1MzdsLS41MjU5ODA3LS4wNTA0NzA4Yy0xLjAzOTA3NDItLjA4NDIxMjYtMi4wMDA3ODYxLS4wNjk4MTAxLTIuODg0NDMwMi4wMTE1NDYybC0uNDM1MzEzMi4wNDYxMTExYy0uMDcxNDY2OC4wMDg1NjYyLS4xNDIzOTA3LjAxNzU2MDgtLjIxMjc3MTIuMDI2OTY1M2wtLjQxNTc1OTUuMDYxMjAwNS0uNDAyNjk5MS4wNzAxNjA3LS4zODk2MTk0LjA3ODI0MTUtLjM3NjUxOTguMDg1NDQyN2MtLjA2MTY2MDYuMDE0NzkxNy0uMTIyNzc0Ni4wMjk4NDY4LS4xODMzNDE1LjA0NTE0N2wtLjM1NjgzMzkuMDk0NTk1Ny0uMzQzNjg1NC4wOTk1OTgyLS4zMzA1MTc0LjEwMzcyMTMtLjMxNzMyOTcuMTA2OTY0OS0uMzA0MTIyNS4xMDkzMjktLjI5MDg5NTYuMTEwODEzNy0uNDExNTAwMi4xNjcwODAzLS41MDIxOTAyLjIxOTc2MTUtLjY1MzM3MzYuMzA4ODk1Ni0uNjEwMTA1LjMwMDU2NzVjLTQuNjk4ODg2NiAyLjYyMTk3ODgtNi44NTM5Mjk0IDYuODQ2MDcxMS03Ljc2ODIwMDIgMTAuODg2NjQ2M2wtLjEyMjMxMDEuNTc1NzgzOGMtLjAzODA1MDQuMTkxMzgzMy0uMDczNDI3OC4zODIxNTc2LS4xMDYyNzMyLjU3MjEzMDFsLS4wOTEwODA0LjU2NzMxOTYtLjA3NjczMTguNTYxMzUyMS0uMDYzMjI3NS41NTQyMjc3Yy0uMDA5NDU5NC4wOTE3MTM0LS4wMTgzOTE0LjE4MzA4MTctLjAyNjgxMzQuMjc0MDgwOGwtLjA0NDU1NC41NDEzNzIyLS4wMzMxNjAxLjUzMTM1NTZjLS4wMDQ2MjQyLjA4NzY2MDMtLjAwODgwODcuMTc0ODU1MS0uMDEyNTcxMy4yNjE1NjAybC0uMDE3NjUyNS41MTQxNjE4LS4wMDgzNjkzLjUwMTI1MzEuMDAwMDY5Ni40ODcxODc2LjAxNDA4MDYuNzAxODc3OS4wMjgzMTk1LjY2MzcyMjkuMDM5NzA4OS42MjE2NjM3LjA0ODI0OTIuNTc1Njk5OS4wNTM5NDAyLjUyNTgzMTcuMDc1ODQ4MS42MTY3ODc5LjA3NDE0NjIuNTExOTM3LjA4MDAwMDIuNDc4Mzc1Ni4wNjg1OTk1LjM1NDA4NjNoLTE3Ljg1NTMxN2wuMDU4NDktLjQ0MTcyNTMuMDQ2MzM2OC0uMjk1MTQ0OC4wNjMwMjA2LS4zNjQ3MjQyLjExMzI4MTktLjU4OTIwNjkuMTA5Mzc4Ny0uNTE1MDkwNy4xODIwMjY1LS43Nzg1MDg4LjE2NjEzNzYtLjY0ODY3NzIuMTI1OTIzMy0uNDYxNTk0My4yMTMwNDc0LS43MzM4MjI1LjE1ODk2NTUtLjUxNTUwNDIuMTczMTcyOC0uNTM1NDY5OS4xODc5NDYzLS41NTQ1MjI2LjIwMzI4NTctLjU3MjY2Mi4yMTkxOTEzLS41ODk4ODgzLjIzNTY2MjgtLjYwNjIwMTQuMjUyNzAwNC0uNjIxNjAxMmMuMDQzNTY4LS4xMDQ4MzI4LjA4Nzg2OTQtLjIxMDI2OTEuMTMyOTE2Mi0uMzE2MjkwMWwuMjc5MzE4LS42NDI5ODg3LjI5Nzc3MDctLjY1NjEwNTYuMzE2Nzg5NC0uNjY4MzA5Mi4zMzYzNzQtLjY3OTU5OTcuMzU2NTI0OS0uNjg5OTc3Yy4zNjY3ODg5LS42OTQ4NjExLjc2NDY1MjktMS40MDM5MTg0IDEuMTk2MTM5My0yLjEyMzA2MjQgNC43NDYzNTAxLTcuOTEwNTgzNCAxMi44Mzc3NDY5LTEzLjkwMDAyNTIgMTkuNDE0ODMyLTE0LjQ4NzY2ODYgNS4wNDUzODA2LS41MDU0MDk0IDkuODkyNTQzNi45Mjc2ODIzIDEzLjk0NDM2MjggMi44Nzk2NDM1bC42NDk5ODU4LjMyMDg1ODIuNjM1NDc2OC4zMjg2MDkzLjYyMDQwMTkuMzM1MDE1Yy4xMDIxMTI2LjA1NjI5NDkuMjAzNTczNi4xMTI4MDA3LjMwNDM3MS4xNjk0ODkybC41OTY3Mjg2LjM0MjEwMTMuNTgwMjM5LjM0NTE0MzkuNTYzMTgzNi4zNDY4NDExLjU0NTU2MjQuMzQ3MTkzMi41MjczNzUzLjM0NjE5OTkuNTA4NjIyMy4zNDM4NjE0Yy4wODMxNzYyLjA1NzA0MDYuMTY1NTQ3NS4xMTM5Mjc3LjI0NzEwMi4xNzA2MzMzbC40Nzk0MzIuMzM3ODMxMi40NTkyNjQ0LjMzMjEyOTQuNDM4NTMxLjMyNTA4MjUuNDE3MjMxNy4zMTY2OTAyLjU4NDY3MzYuNDU2MzU2OS41MzM1Njc0LjQyOTkwNzEuNjI4NjIzNy41MjQyMTc5LjY0NjM0MzIuNTYxNDAxNXptLTMwLjcwMDEwNTYgMTQuNTcxMzI0MyAyLjQ0MDk4MDEuODgxNDY1Yy4xMTMwMDgzLjg4NTIzMTkuMjczMTAzNCAxLjcyMzM3NzEuNDQxMDQ2NCAyLjQ4ODI3NjFsLjEwMTM5MzYuNDQ5OTQwNi0yLjcxMjIwMDEtLjk3MTg3MTctLjAzMzgzNDctLjIxMjE2MTgtLjA2NjA0MjEtLjQ3NTU4NDMtLjA2MTE2MDEtLjU0MTIxOTVjLS4wNDgwMjg1LS40Nzc0NjAyLS4wODc1ODE0LTEuMDE5OTAwMy0uMTEwMTgzMS0xLjYxODg0NDR6bTMxLjUwNjcyMzktNy42NjE5NjUyaC0xLjUxNDMxMTdjLS45NDAwMjM4IDAtMS4yMzkxMjI0LjQwOTc3Mi0xLjMzNDI5MDEuNjcwNTM2bC0uMDI4MjI2Ni4wOTUwMzM5Yy0uMDAzMjM3LjAxNDA3My0uMDA1ODI2Ni4wMjcxNTI2LS4wMDc4OTgyLjAzOTA3MzJsLS4wMDgxNTczLjA3MTUyMzktLjAwMDEyOTUgMy45MTUzODY0aDQuMTM2MTA1MWwtLjAwMTg1MzMtMy45MzQ3Njk0LS4wMTAyNjEyLS4wNjY5OTEzLS4wMjU3MjA3LS4wOTg3MjQxYy0uMDgzNTM1Ny0uMjU5MTUwNy0uMzUwOTEzNS0uNjkxMDY4Ni0xLjIwNTI1NjUtLjY5MTA2ODZ6bS01MC40OTIxMjQyLjMzOTAyNSAyLjU5OTE5MTcuOTQ5MjctLjQwODY0MS45NTE1ODM5Yy0uMjEyNDg4Mi40OTk0NjQ0LS40Mjc3Nzk2IDEuMDE0ODE0Mi0uNjAzMzU3NSAxLjQ1Nzc0NWwtLjExODA4NDkuMzAyODcxMi0yLjU5OTE5MTctLjk0OTI3LjEzMjM2NjItLjM0NTMwMzMuMjU4Mzg4OS0uNjM5MjAzNC4zMDU3MTExLS43MjgxOTc0LjMyNTQ4NzUtLjc1MzYyNDRjLjAzNjI0MzgtLjA4Mjc5NDMuMDcyMzQzNy0uMTY0ODgyMy4xMDgxMjk3LS4yNDU4NzE2em0zNS40NDUxMjA5LS4xNDM0NDQ5aC0zLjQ1Njg0Mzl2My42NTg4NjczaDMuNDM0Mzk2OGwuMDU0NzEwNi0uMDI1MzkyLjA4NjU5ODQtLjA0ODg5ODMuMTE0NzUzNi0uMDc4NjgyMmMuMjkyNjQyOC0uMjIxMTQ0OC43MzE2MDcxLS43MTQ5Nzk3LjczMTYwNzEtMS42ODc2ODQ3cy0uNDI4OTg3OC0xLjQ1NjU2MzQtLjcxNDk3OTctMS42NzEwNTczbC0uMTEyMTQ1NS0uMDc2MDc0MS0uMDg0NjMwMy0uMDQ2OTMwMXptLTE1LjQ0MjY0NTYtLjc2MDYyMTggMS42MjczMjAxIDEuMjg4Mjk1MWMtLjE4MDgxMzQuNzA1MTcyLS4zMTgyMzE1IDEuNDEwMzQ0LS40MTIyNTQ1IDIuMTE1NTE2bC0uMDYyMzgwNi41Mjg4NzktMS44MzA3MzUtMS40NDY1MDY3Yy4xODA4MTM0LS44MTM2Ni4zODQyMjg0LTEuNjQ5OTIxNy42NzgwNS0yLjQ4NjE4MzR6bTQuMDAwNDk1MS02LjMwNTg2NTEgMS4wMTcwNzUgMS41MzY5MTM0Yy0uMzk3Nzg5My40MTU4NzA3LS43NjY2NDg1LjgzMTc0MTMtMS4wOTUwMDU1IDEuMjcwNzU2MWwtLjIzODQ5MjguMzMzOTYyMy0xLjA4NDg4MDEtMS42MjczMjAxYy40MDY4My0uNTE5ODM4My44ODE0NjUxLTEuMDM5Njc2NyAxLjQwMTMwMzQtMS41MTQzMTE3em0tMTYuMTgyNzkzNi0zLjM0NTA0NjcgMS42MDQ3MTgzIDEuNDAxMzAzNGMtLjQwNjgzLjQyMzc4MTItLjgwMDk0NjUuODcyOTg5NC0xLjE3MjgxNDYgMS4zMjg1NTQybC0uMzY0MDk4Ny40NTY5Nzc1LTEuNzQwMzI4NC0xLjQ5MTcxMDFjLjUxOTgzODMtLjU2NTA0MTYgMS4wODQ4OC0xLjEzMDA4MzMgMS42NzI1MjM0LTEuNjk1MTI1em0yMi4zOTgyNTIxLS4wOTA0MDY3LjQ5NzIzNjYgMS40OTE3MTAxYy0uNTI0MzU4Ni4xNjI3MzItMS4wNDg3MTczLjM2ODg1OTItMS41NzMwNzYuNjA2ODA5NWwtLjM5MzI2OS4xODQyNDg4LS41MTk4Mzg0LTEuNTU5NTE1Yy41NjUwNDE3LS4yNDg2MTg0IDEuMjIwNDkwMS0uNDk3MjM2NyAxLjk4ODk0NjgtLjcyMzI1MzR6bTUuMjg4NzktLjU0MjQ0Yy41Nzg2MDI3LjAzNjE2MjcgMS4xNzE2NzA1LjEwMTI1NTUgMS43NzkyMDMzLjIwNjg1MDVsLjQ1ODM2MTguMDg2OTcxMi0uMDkwNDA2NyAxLjQwMTMwMzRjLS41OTY2ODQtLjEyNjU2OTQtMS4xOTMzNjgtLjIwOTc0MzUtMS43OTAwNTItLjI0OTUyMjRsLS40NDc1MTMtLjAyMTY5NzZ6bS0xOC41NTU5Njg2LTYuMjM4MDYwMSAxLjAxNzA3NSAxLjU1OTUxNWMtLjQ0MDczMjUuMjIwMzY2My0uODY4NzUxNi40NjYxNTk0LTEuMzAzMTI3NC43Mjc4NDQzbC0uNDM3MjAxLjI2NjYyOTEtMS4wMzk2NzY3LTEuNTgyMTE2N2MuNjEwMjQ1LS4zNjE2MjY3IDEuMTk3ODg4NC0uNjc4MDUgMS43NjI5MzAxLS45NzE4NzE3em0xOC41MTA3NjUzLjYzMjg0NjcuMDkwNDA2Ny0xLjQ5MTcxLjQ0MzUwNzMuMTMwNTU2NC4zODM5ODAzLjEyMDMyNTIuMzI4NTQ1OC4xMDk5MDc5LjI3NzIwMzcuMDk5MzA0OC4zMjg0OTE1LjEyODY2OS4yOTY0ODguMTMyNzExMi4xMzQxNDUxLjA2OTU4MzgtLjA5MDQwNjcgMS41MTQzMTE3Yy0uNDgyMTY4OS0uMTk1ODgxMS0uOTY0MzM3OC0uMzgxNzE3LTEuNDUzMjAzNS0uNTU3NTA3OHptLTguNTQzNDMwMS0yLjgyNTIwODQuNDUyMDMzMyAxLjM3ODcwMTdoLS4yMjYwMTY3Yy0uNDkxNTg2MiAwLS45ODMxNzI1LjAxMjcxMzQtMS40NzQ3NTg4LjA0NzY3NTRsLS40OTE1ODYyLjA0MjczMTMtLjQyOTQzMTctMS4zMzM0OTg0Yy43NDU4NTUtLjA5MDQwNjcgMS40NjkxMDg0LS4xMzU2MSAyLjE2OTc2MDEtLjEzNTYxeiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==" />
98
+ <img alt="Ruby on Rails Logo" src="data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjExMiIgdmlld0JveD0iMCAwIDExMiAxMTIiIHdpZHRoPSIxMTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTEwMC4wODIzNTcgNDguOTk5NTQwM3Y0LjExMzUwMzRoLTcuMzAwMzM4OHYxLjg5ODU0aDMuNjg0MDcxN2MxLjk3MjUwOTEgMCA0LjA3MjUzNDEgMS40NjY0MzExIDQuMTk3OTk3MSAzLjk2NjUxMjRsLjAwNTkxMy4yMzczOTc3djEuNTgyMTE2N2MtLjA4NzgyNCAzLjAwNzk1OS0yLjU0MzEyMTEgNC4xMzkwMDE4LTQuMDcxNTM4OSA0LjIwMTE3NzNsLS4xMzIzNzEyLjAwMjczMjhoLTcuMzkwNzQ1MXYtNC4wOTA5MDE4bDcuNDgxMTUxOC0uMDIyNjAxNnYtMS45ODg5NDY3aC0zLjQ4MDY1NjdjLTEuNzc1MjU4MyAwLTQuMDgxODMyMS0xLjMzODkxNTMtNC4yMTk5OTQyLTMuOTU0OTIwMWwtLjAwNjUxNzYtLjI0ODk5di0xLjQyMzkwNWMwLTIuNjk4MjQwMiAyLjI3ODIxMjktNC4xODI4NTMgNC4wNjU0NjQtNC4yNjc4NDkxbC4xNjEwNDc4LS4wMDM4NjZ6bS0xOC42OTE1NzkgMHYxMS44NjU4NzUyaDYuMTcwMjU1MXY0LjEzNjEwNTFoLTEwLjczNTc5MTl2LTE2LjAwMTk4MDN6bS02LjQ0MTQ3NTEgMHYxNi4wMDE5ODAzaC00LjU4ODEzODV2LTE2LjAwMTk4MDN6bS0xNS4yMTA5MjIgMGg0LjQwNzMyNTFsLjE4NzcyNC4wMDY2ODEyYy4wMzM4NjA5LjAwMjI3MzUuMDY4OTQ1Ny4wMDUxNDk5LjEwNTE2MDEuMDA4NjY0M2wuMjMwMDg3NS4wMjkwMTc4YzEuMjkxMzgyOS4xOTg1NDc2IDMuNTQ2MzgxNiAxLjEyMTM4MTYgMy42NzUxNzA4IDMuOTA2ODU4N2wuMDA1NzY3Ny4yNTI2ODgxdjExLjc5ODA3MDJoLTQuMjcxNzE1MXYtMi44MjUyMDg0aC00LjEzNjEwNTF2Mi44MjUyMDg0aC00LjQwNzMyNTF2LTExLjc5ODA3MDJjMC0xLjMxODQzMDYgMS4wMDQwODI2LTQuMDQ2ODQ5NSAzLjk0Njg5OS00LjE5NzQxMXptLTE5LjczOTg1MTktLjAwMjc1ODEgOC41ODAxODU3LjAwMDU3NDkuMjM4OTIzNC4wMzY3NDYyLjE0Nzk0NTkuMDI5NDE3LjI3NDExNjEuMDY1MzU4Mi4yMTI1MTk4LjA1OTkwNjguMjMyMzIyNS4wNzQ3MTgyYy4wNDAxNzkzLjAxMzc3MDQuMDgxMDQwMi4wMjgyMjAxLjEyMjUxMS4wNDMzODA0bC4yNTU1NjkxLjA5OTczNzYuMjY2NzYxOC4xMTgyODUyYzEuMzU2MDUxNS42NDAyODY2IDMuMDAyNjg1NSAyLjAzMjE1ODMgMy4wMDI2ODU1IDUuMDE2Mjk0IDAgMy4xODMwNzgxLTEuNTQ2NTI0MSA0LjUwMTQ4OTktMi42OTg4MzYyIDUuMDQyMDQ3N2wtLjIxMDk2NTEuMDkyNTA0NS0uMTk4ODgyOC4wNzU4NjU1LS4xODM5NTc3LjA2MDgxODYtLjE2NjE4OTguMDQ3MzYzNi0uMjA5NzUwOC4wNDkzMDAxLS4yNTk2NDkzLjA0MTgzNjMgNS4wMDU2ODk1IDUuMDUwNTgzNmgtNi4zNzQ5NTg5bC0zLjcyNjIwODMtMy44NjA4OTA2djMuODYwODkwNmgtNC4zMDk4MzE0em0yMi4wMDcwNjAzLTMuMDg2OTE5My40NDQ5OTE3LjQyMjY4MDctLjI0Mjk2OC4xNzc5ODgxLS4zNDgyMzMxLjI2OTMzNjUtLjE5OTg1NzMuMTYyOTIwNGMtNS4yMzk4OTY3LTMuODc0NTcxNS05LjY0NzY0NTQtNS40MjIxNDA5LTEzLjE5NzExOS01LjgxNTM1MzdsLS41MjU5ODA3LS4wNTA0NzA4Yy0xLjAzOTA3NDItLjA4NDIxMjYtMi4wMDA3ODYxLS4wNjk4MTAxLTIuODg0NDMwMi4wMTE1NDYybC0uNDM1MzEzMi4wNDYxMTExYy0uMDcxNDY2OC4wMDg1NjYyLS4xNDIzOTA3LjAxNzU2MDgtLjIxMjc3MTIuMDI2OTY1M2wtLjQxNTc1OTUuMDYxMjAwNS0uNDAyNjk5MS4wNzAxNjA3LS4zODk2MTk0LjA3ODI0MTUtLjM3NjUxOTguMDg1NDQyN2MtLjA2MTY2MDYuMDE0NzkxNy0uMTIyNzc0Ni4wMjk4NDY4LS4xODMzNDE1LjA0NTE0N2wtLjM1NjgzMzkuMDk0NTk1Ny0uMzQzNjg1NC4wOTk1OTgyLS4zMzA1MTc0LjEwMzcyMTMtLjMxNzMyOTcuMTA2OTY0OS0uMzA0MTIyNS4xMDkzMjktLjI5MDg5NTYuMTEwODEzNy0uNDExNTAwMi4xNjcwODAzLS41MDIxOTAyLjIxOTc2MTUtLjY1MzM3MzYuMzA4ODk1Ni0uNjEwMTA1LjMwMDU2NzVjLTQuNjk4ODg2NiAyLjYyMTk3ODgtNi44NTM5Mjk0IDYuODQ2MDcxMS03Ljc2ODIwMDIgMTAuODg2NjQ2M2wtLjEyMjMxMDEuNTc1NzgzOGMtLjAzODA1MDQuMTkxMzgzMy0uMDczNDI3OC4zODIxNTc2LS4xMDYyNzMyLjU3MjEzMDFsLS4wOTEwODA0LjU2NzMxOTYtLjA3NjczMTguNTYxMzUyMS0uMDYzMjI3NS41NTQyMjc3Yy0uMDA5NDU5NC4wOTE3MTM0LS4wMTgzOTE0LjE4MzA4MTctLjAyNjgxMzQuMjc0MDgwOGwtLjA0NDU1NC41NDEzNzIyLS4wMzMxNjAxLjUzMTM1NTZjLS4wMDQ2MjQyLjA4NzY2MDMtLjAwODgwODcuMTc0ODU1MS0uMDEyNTcxMy4yNjE1NjAybC0uMDE3NjUyNS41MTQxNjE4LS4wMDgzNjkzLjUwMTI1MzEuMDAwMDY5Ni40ODcxODc2LjAxNDA4MDYuNzAxODc3OS4wMjgzMTk1LjY2MzcyMjkuMDM5NzA4OS42MjE2NjM3LjA0ODI0OTIuNTc1Njk5OS4wNTM5NDAyLjUyNTgzMTcuMDc1ODQ4MS42MTY3ODc5LjA3NDE0NjIuNTExOTM3LjA4MDAwMDIuNDc4Mzc1Ni4wNjg1OTk1LjM1NDA4NjNoLTE3Ljg1NTMxN2wuMDU4NDktLjQ0MTcyNTMuMDQ2MzM2OC0uMjk1MTQ0OC4wNjMwMjA2LS4zNjQ3MjQyLjExMzI4MTktLjU4OTIwNjkuMTA5Mzc4Ny0uNTE1MDkwNy4xODIwMjY1LS43Nzg1MDg4LjE2NjEzNzYtLjY0ODY3NzIuMTI1OTIzMy0uNDYxNTk0My4yMTMwNDc0LS43MzM4MjI1LjE1ODk2NTUtLjUxNTUwNDIuMTczMTcyOC0uNTM1NDY5OS4xODc5NDYzLS41NTQ1MjI2LjIwMzI4NTctLjU3MjY2Mi4yMTkxOTEzLS41ODk4ODgzLjIzNTY2MjgtLjYwNjIwMTQuMjUyNzAwNC0uNjIxNjAxMmMuMDQzNTY4LS4xMDQ4MzI4LjA4Nzg2OTQtLjIxMDI2OTEuMTMyOTE2Mi0uMzE2MjkwMWwuMjc5MzE4LS42NDI5ODg3LjI5Nzc3MDctLjY1NjEwNTYuMzE2Nzg5NC0uNjY4MzA5Mi4zMzYzNzQtLjY3OTU5OTcuMzU2NTI0OS0uNjg5OTc3Yy4zNjY3ODg5LS42OTQ4NjExLjc2NDY1MjktMS40MDM5MTg0IDEuMTk2MTM5My0yLjEyMzA2MjQgNC43NDYzNTAxLTcuOTEwNTgzNCAxMi44Mzc3NDY5LTEzLjkwMDAyNTIgMTkuNDE0ODMyLTE0LjQ4NzY2ODYgNS4wNDUzODA2LS41MDU0MDk0IDkuODkyNTQzNi45Mjc2ODIzIDEzLjk0NDM2MjggMi44Nzk2NDM1bC42NDk5ODU4LjMyMDg1ODIuNjM1NDc2OC4zMjg2MDkzLjYyMDQwMTkuMzM1MDE1Yy4xMDIxMTI2LjA1NjI5NDkuMjAzNTczNi4xMTI4MDA3LjMwNDM3MS4xNjk0ODkybC41OTY3Mjg2LjM0MjEwMTMuNTgwMjM5LjM0NTE0MzkuNTYzMTgzNi4zNDY4NDExLjU0NTU2MjQuMzQ3MTkzMi41MjczNzUzLjM0NjE5OTkuNTA4NjIyMy4zNDM4NjE0Yy4wODMxNzYyLjA1NzA0MDYuMTY1NTQ3NS4xMTM5Mjc3LjI0NzEwMi4xNzA2MzMzbC40Nzk0MzIuMzM3ODMxMi40NTkyNjQ0LjMzMjEyOTQuNDM4NTMxLjMyNTA4MjUuNDE3MjMxNy4zMTY2OTAyLjU4NDY3MzYuNDU2MzU2OS41MzM1Njc0LjQyOTkwNzEuNjI4NjIzNy41MjQyMTc5LjY0NjM0MzIuNTYxNDAxNXptLTMwLjcwMDEwNTYgMTQuNTcxMzI0MyAyLjQ0MDk4MDEuODgxNDY1Yy4xMTMwMDgzLjg4NTIzMTkuMjczMTAzNCAxLjcyMzM3NzEuNDQxMDQ2NCAyLjQ4ODI3NjFsLjEwMTM5MzYuNDQ5OTQwNi0yLjcxMjIwMDEtLjk3MTg3MTctLjAzMzgzNDctLjIxMjE2MTgtLjA2NjA0MjEtLjQ3NTU4NDMtLjA2MTE2MDEtLjU0MTIxOTVjLS4wNDgwMjg1LS40Nzc0NjAyLS4wODc1ODE0LTEuMDE5OTAwMy0uMTEwMTgzMS0xLjYxODg0NDR6bTMxLjUwNjcyMzktNy42NjE5NjUyaC0xLjUxNDMxMTdjLS45NDAwMjM4IDAtMS4yMzkxMjI0LjQwOTc3Mi0xLjMzNDI5MDEuNjcwNTM2bC0uMDI4MjI2Ni4wOTUwMzM5Yy0uMDAzMjM3LjAxNDA3My0uMDA1ODI2Ni4wMjcxNTI2LS4wMDc4OTgyLjAzOTA3MzJsLS4wMDgxNTczLjA3MTUyMzktLjAwMDEyOTUgMy45MTUzODY0aDQuMTM2MTA1MWwtLjAwMTg1MzMtMy45MzQ3Njk0LS4wMTAyNjEyLS4wNjY5OTEzLS4wMjU3MjA3LS4wOTg3MjQxYy0uMDgzNTM1Ny0uMjU5MTUwNy0uMzUwOTEzNS0uNjkxMDY4Ni0xLjIwNTI1NjUtLjY5MTA2ODZ6bS01MC40OTIxMjQyLjMzOTAyNSAyLjU5OTE5MTcuOTQ5MjctLjQwODY0MS45NTE1ODM5Yy0uMjEyNDg4Mi40OTk0NjQ0LS40Mjc3Nzk2IDEuMDE0ODE0Mi0uNjAzMzU3NSAxLjQ1Nzc0NWwtLjExODA4NDkuMzAyODcxMi0yLjU5OTE5MTctLjk0OTI3LjEzMjM2NjItLjM0NTMwMzMuMjU4Mzg4OS0uNjM5MjAzNC4zMDU3MTExLS43MjgxOTc0LjMyNTQ4NzUtLjc1MzYyNDRjLjAzNjI0MzgtLjA4Mjc5NDMuMDcyMzQzNy0uMTY0ODgyMy4xMDgxMjk3LS4yNDU4NzE2em0zNS40NDUxMjA5LS4xNDM0NDQ5aC0zLjQ1Njg0Mzl2My42NTg4NjczaDMuNDM0Mzk2OGwuMDU0NzEwNi0uMDI1MzkyLjA4NjU5ODQtLjA0ODg5ODMuMTE0NzUzNi0uMDc4NjgyMmMuMjkyNjQyOC0uMjIxMTQ0OC43MzE2MDcxLS43MTQ5Nzk3LjczMTYwNzEtMS42ODc2ODQ3cy0uNDI4OTg3OC0xLjQ1NjU2MzQtLjcxNDk3OTctMS42NzEwNTczbC0uMTEyMTQ1NS0uMDc2MDc0MS0uMDg0NjMwMy0uMDQ2OTMwMXptLTE1LjQ0MjY0NTYtLjc2MDYyMTggMS42MjczMjAxIDEuMjg4Mjk1MWMtLjE4MDgxMzQuNzA1MTcyLS4zMTgyMzE1IDEuNDEwMzQ0LS40MTIyNTQ1IDIuMTE1NTE2bC0uMDYyMzgwNi41Mjg4NzktMS44MzA3MzUtMS40NDY1MDY3Yy4xODA4MTM0LS44MTM2Ni4zODQyMjg0LTEuNjQ5OTIxNy42NzgwNS0yLjQ4NjE4MzR6bTQuMDAwNDk1MS02LjMwNTg2NTEgMS4wMTcwNzUgMS41MzY5MTM0Yy0uMzk3Nzg5My40MTU4NzA3LS43NjY2NDg1LjgzMTc0MTMtMS4wOTUwMDU1IDEuMjcwNzU2MWwtLjIzODQ5MjguMzMzOTYyMy0xLjA4NDg4MDEtMS42MjczMjAxYy40MDY4My0uNTE5ODM4My44ODE0NjUxLTEuMDM5Njc2NyAxLjQwMTMwMzQtMS41MTQzMTE3em0tMTYuMTgyNzkzNi0zLjM0NTA0NjcgMS42MDQ3MTgzIDEuNDAxMzAzNGMtLjQwNjgzLjQyMzc4MTItLjgwMDk0NjUuODcyOTg5NC0xLjE3MjgxNDYgMS4zMjg1NTQybC0uMzY0MDk4Ny40NTY5Nzc1LTEuNzQwMzI4NC0xLjQ5MTcxMDFjLjUxOTgzODMtLjU2NTA0MTYgMS4wODQ4OC0xLjEzMDA4MzMgMS42NzI1MjM0LTEuNjk1MTI1em0yMi4zOTgyNTIxLS4wOTA0MDY3LjQ5NzIzNjYgMS40OTE3MTAxYy0uNTI0MzU4Ni4xNjI3MzItMS4wNDg3MTczLjM2ODg1OTItMS41NzMwNzYuNjA2ODA5NWwtLjM5MzI2OS4xODQyNDg4LS41MTk4Mzg0LTEuNTU5NTE1Yy41NjUwNDE3LS4yNDg2MTg0IDEuMjIwNDkwMS0uNDk3MjM2NyAxLjk4ODk0NjgtLjcyMzI1MzR6bTUuMjg4NzktLjU0MjQ0Yy41Nzg2MDI3LjAzNjE2MjcgMS4xNzE2NzA1LjEwMTI1NTUgMS43NzkyMDMzLjIwNjg1MDVsLjQ1ODM2MTguMDg2OTcxMi0uMDkwNDA2NyAxLjQwMTMwMzRjLS41OTY2ODQtLjEyNjU2OTQtMS4xOTMzNjgtLjIwOTc0MzUtMS43OTAwNTItLjI0OTUyMjRsLS40NDc1MTMtLjAyMTY5NzZ6bS0xOC41NTU5Njg2LTYuMjM4MDYwMSAxLjAxNzA3NSAxLjU1OTUxNWMtLjQ0MDczMjUuMjIwMzY2My0uODY4NzUxNi40NjYxNTk0LTEuMzAzMTI3NC43Mjc4NDQzbC0uNDM3MjAxLjI2NjYyOTEtMS4wMzk2NzY3LTEuNTgyMTE2N2MuNjEwMjQ1LS4zNjE2MjY3IDEuMTk3ODg4NC0uNjc4MDUgMS43NjI5MzAxLS45NzE4NzE3em0xOC41MTA3NjUzLjYzMjg0NjcuMDkwNDA2Ny0xLjQ5MTcxLjQ0MzUwNzMuMTMwNTU2NC4zODM5ODAzLjEyMDMyNTIuMzI4NTQ1OC4xMDk5MDc5LjI3NzIwMzcuMDk5MzA0OC4zMjg0OTE1LjEyODY2OS4yOTY0ODguMTMyNzExMi4xMzQxNDUxLjA2OTU4MzgtLjA5MDQwNjcgMS41MTQzMTE3Yy0uNDgyMTY4OS0uMTk1ODgxMS0uOTY0MzM3OC0uMzgxNzE3LTEuNDUzMjAzNS0uNTU3NTA3OHptLTguNTQzNDMwMS0yLjgyNTIwODQuNDUyMDMzMyAxLjM3ODcwMTdoLS4yMjYwMTY3Yy0uNDkxNTg2MiAwLS45ODMxNzI1LjAxMjcxMzQtMS40NzQ3NTg4LjA0NzY3NTRsLS40OTE1ODYyLjA0MjczMTMtLjQyOTQzMTctMS4zMzM0OTg0Yy43NDU4NTUtLjA5MDQwNjcgMS40NjkxMDg0LS4xMzU2MSAyLjE2OTc2MDEtLjEzNTYxeiIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==" />
83
99
  </a>
84
100
  </nav>
85
101
 
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/class/attribute"
4
3
  require "minitest"
5
4
 
6
5
  module Rails
7
6
  class TestUnitReporter < Minitest::StatisticsReporter
8
- class_attribute :app_root
9
- class_attribute :executable, default: "bin/rails test"
7
+ singleton_class.attr_accessor :app_root
8
+
9
+ @executable = "bin/rails test"
10
+ singleton_class.attr_accessor :executable
10
11
 
11
12
  def prerecord(test_class, test_name)
12
13
  super
@@ -86,7 +87,7 @@ module Rails
86
87
  result.method(result.name).source_location
87
88
  end
88
89
 
89
- "#{executable} #{relative_path_for(location)}:#{line}"
90
+ "#{self.class.executable} #{relative_path_for(location)}:#{line}"
90
91
  end
91
92
 
92
93
  def app_root
@@ -26,6 +26,7 @@ module Rails
26
26
  TEST_FOLDERS = [:models, :helpers, :channels, :controllers, :mailers, :integration, :jobs, :mailboxes]
27
27
  PATH_ARGUMENT_PATTERN = %r"^(?!/.+/$)[.\w]*[/\\]"
28
28
  mattr_reader :filters, default: []
29
+ mattr_reader :load_test_files, default: false
29
30
 
30
31
  class << self
31
32
  def attach_before_load_options(opts)
@@ -52,10 +53,14 @@ module Rails
52
53
  success || exit(false)
53
54
  end
54
55
 
55
- def run(argv = [])
56
- load_tests(argv)
57
-
56
+ def run(args = [])
58
57
  require "active_support/testing/autorun"
58
+
59
+ @@load_test_files = true
60
+
61
+ at_exit do
62
+ ARGV.replace(args)
63
+ end
59
64
  end
60
65
 
61
66
  def load_tests(argv)
@@ -93,8 +98,6 @@ module Rails
93
98
  def extract_filters(argv)
94
99
  # Extract absolute and relative paths but skip -n /.*/ regexp filters.
95
100
  argv.filter_map do |path|
96
- next unless path_argument?(path)
97
-
98
101
  path = path.tr("\\", "/")
99
102
  case
100
103
  when /(:\d+(-\d+)?)+$/.match?(path)
data/lib/rails.rb CHANGED
@@ -3,10 +3,9 @@
3
3
  require "pathname"
4
4
 
5
5
  require "active_support"
6
+ require "active_support/rails"
6
7
  require "active_support/core_ext/kernel/reporting"
7
- require "active_support/core_ext/module/delegation"
8
8
  require "active_support/core_ext/array/extract_options"
9
- require "active_support/core_ext/object/blank"
10
9
 
11
10
  require "rails/version"
12
11
  require "rails/deprecator"
@@ -94,6 +93,14 @@ module Rails
94
93
  ActiveSupport.error_reporter
95
94
  end
96
95
 
96
+ # Returns the ActiveSupport::EventReporter of the current \Rails project,
97
+ # otherwise it returns +nil+ if there is no project.
98
+ #
99
+ # Rails.event.notify("my_event", { message: "Hello, world!" })
100
+ def event
101
+ ActiveSupport.event_reporter
102
+ end
103
+
97
104
  # Returns all \Rails groups for loading based on:
98
105
  #
99
106
  # * The \Rails environment;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: railties
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.3
4
+ version: 8.1.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -15,28 +15,28 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 8.0.3
18
+ version: 8.1.0.rc1
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 8.0.3
25
+ version: 8.1.0.rc1
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: actionpack
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - '='
31
31
  - !ruby/object:Gem::Version
32
- version: 8.0.3
32
+ version: 8.1.0.rc1
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 8.0.3
39
+ version: 8.1.0.rc1
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: rackup
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -133,14 +133,14 @@ dependencies:
133
133
  requirements:
134
134
  - - '='
135
135
  - !ruby/object:Gem::Version
136
- version: 8.0.3
136
+ version: 8.1.0.rc1
137
137
  type: :development
138
138
  prerelease: false
139
139
  version_requirements: !ruby/object:Gem::Requirement
140
140
  requirements:
141
141
  - - '='
142
142
  - !ruby/object:Gem::Version
143
- version: 8.0.3
143
+ version: 8.1.0.rc1
144
144
  description: 'Rails internals: application bootup, plugins, generators, and rake tasks.'
145
145
  email: david@loudthinking.com
146
146
  executables:
@@ -219,7 +219,6 @@ files:
219
219
  - lib/rails/commands/unused_routes/unused_routes_command.rb
220
220
  - lib/rails/commands/version/version_command.rb
221
221
  - lib/rails/configuration.rb
222
- - lib/rails/console/methods.rb
223
222
  - lib/rails/deprecator.rb
224
223
  - lib/rails/dev_caching.rb
225
224
  - lib/rails/engine.rb
@@ -279,6 +278,8 @@ files:
279
278
  - lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt
280
279
  - lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js
281
280
  - lib/rails/generators/rails/app/templates/bin/brakeman.tt
281
+ - lib/rails/generators/rails/app/templates/bin/bundler-audit.tt
282
+ - lib/rails/generators/rails/app/templates/bin/ci.tt
282
283
  - lib/rails/generators/rails/app/templates/bin/dev.tt
283
284
  - lib/rails/generators/rails/app/templates/bin/rails.tt
284
285
  - lib/rails/generators/rails/app/templates/bin/rake.tt
@@ -288,7 +289,9 @@ files:
288
289
  - lib/rails/generators/rails/app/templates/config.ru.tt
289
290
  - lib/rails/generators/rails/app/templates/config/application.rb.tt
290
291
  - lib/rails/generators/rails/app/templates/config/boot.rb.tt
292
+ - lib/rails/generators/rails/app/templates/config/bundler-audit.yml.tt
291
293
  - lib/rails/generators/rails/app/templates/config/cable.yml.tt
294
+ - lib/rails/generators/rails/app/templates/config/ci.rb.tt
292
295
  - lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt
293
296
  - lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt
294
297
  - lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt
@@ -303,7 +306,7 @@ files:
303
306
  - lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt
304
307
  - lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt
305
308
  - lib/rails/generators/rails/app/templates/config/initializers/inflections.rb.tt
306
- - lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt
309
+ - lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_1.rb.tt
307
310
  - lib/rails/generators/rails/app/templates/config/locales/en.yml
308
311
  - lib/rails/generators/rails/app/templates/config/puma.rb.tt
309
312
  - lib/rails/generators/rails/app/templates/config/routes.rb.tt
@@ -425,9 +428,12 @@ files:
425
428
  - lib/rails/generators/test_case.rb
426
429
  - lib/rails/generators/test_unit.rb
427
430
  - lib/rails/generators/test_unit/authentication/authentication_generator.rb
431
+ - lib/rails/generators/test_unit/authentication/templates/test/controllers/passwords_controller_test.rb.tt
432
+ - lib/rails/generators/test_unit/authentication/templates/test/controllers/sessions_controller_test.rb
428
433
  - lib/rails/generators/test_unit/authentication/templates/test/fixtures/users.yml.tt
429
434
  - lib/rails/generators/test_unit/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt
430
435
  - lib/rails/generators/test_unit/authentication/templates/test/models/user_test.rb.tt
436
+ - lib/rails/generators/test_unit/authentication/templates/test/test_helpers/session_test_helper.rb.tt
431
437
  - lib/rails/generators/test_unit/controller/controller_generator.rb
432
438
  - lib/rails/generators/test_unit/controller/templates/functional_test.rb.tt
433
439
  - lib/rails/generators/test_unit/generator/generator_generator.rb
@@ -443,9 +449,6 @@ files:
443
449
  - lib/rails/generators/test_unit/model/model_generator.rb
444
450
  - lib/rails/generators/test_unit/model/templates/fixtures.yml.tt
445
451
  - lib/rails/generators/test_unit/model/templates/unit_test.rb.tt
446
- - lib/rails/generators/test_unit/plugin/plugin_generator.rb
447
- - lib/rails/generators/test_unit/plugin/templates/%file_name%_test.rb.tt
448
- - lib/rails/generators/test_unit/plugin/templates/test_helper.rb
449
452
  - lib/rails/generators/test_unit/scaffold/scaffold_generator.rb
450
453
  - lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt
451
454
  - lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt
@@ -505,10 +508,10 @@ licenses:
505
508
  - MIT
506
509
  metadata:
507
510
  bug_tracker_uri: https://github.com/rails/rails/issues
508
- changelog_uri: https://github.com/rails/rails/blob/v8.0.3/railties/CHANGELOG.md
509
- documentation_uri: https://api.rubyonrails.org/v8.0.3/
511
+ changelog_uri: https://github.com/rails/rails/blob/v8.1.0.rc1/railties/CHANGELOG.md
512
+ documentation_uri: https://api.rubyonrails.org/v8.1.0.rc1/
510
513
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
511
- source_code_uri: https://github.com/rails/rails/tree/v8.0.3/railties
514
+ source_code_uri: https://github.com/rails/rails/tree/v8.1.0.rc1/railties
512
515
  rubygems_mfa_required: 'true'
513
516
  rdoc_options:
514
517
  - "--exclude"
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Rails.deprecator.warn(<<~MSG, caller_locations(0..1))
4
- `rails/console/methods` has been deprecated and will be removed in Rails 8.1.
5
- Please directly use IRB's extension API to add new commands or helpers to the console.
6
- For more details, please visit: https://github.com/ruby/irb/blob/master/EXTEND_IRB.md
7
- MSG
@@ -1,30 +0,0 @@
1
- # Be sure to restart your server when you modify this file.
2
- #
3
- # This file eases your Rails 8.0 framework defaults upgrade.
4
- #
5
- # Uncomment each configuration one by one to switch to the new default.
6
- # Once your application is ready to run with all new defaults, you can remove
7
- # this file and set the `config.load_defaults` to `8.0`.
8
- #
9
- # Read the Guide for Upgrading Ruby on Rails for more info on each option.
10
- # https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
11
-
12
- ###
13
- # Specifies whether `to_time` methods preserve the UTC offset of their receivers or preserves the timezone.
14
- # If set to `:zone`, `to_time` methods will use the timezone of their receivers.
15
- # If set to `:offset`, `to_time` methods will use the UTC offset.
16
- # If `false`, `to_time` methods will convert to the local system UTC offset instead.
17
- #++
18
- # Rails.application.config.active_support.to_time_preserves_timezone = :zone
19
-
20
- ###
21
- # When both `If-Modified-Since` and `If-None-Match` are provided by the client
22
- # only consider `If-None-Match` as specified by RFC 7232 Section 6.
23
- # If set to `false` both conditions need to be satisfied.
24
- #++
25
- # Rails.application.config.action_dispatch.strict_freshness = true
26
-
27
- ###
28
- # Set `Regexp.timeout` to `1`s by default to improve security over Regexp Denial-of-Service attacks.
29
- #++
30
- # Regexp.timeout = 1