railties 8.1.0.beta1 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -0
- data/lib/rails/application/bootstrap.rb +1 -1
- data/lib/rails/application/configuration.rb +5 -9
- data/lib/rails/code_statistics.rb +4 -1
- data/lib/rails/commands/app/update_command.rb +1 -0
- data/lib/rails/gem_version.rb +1 -1
- data/lib/rails/generators/app_base.rb +12 -0
- data/lib/rails/generators/rails/app/app_generator.rb +6 -5
- data/lib/rails/generators/rails/app/templates/Dockerfile.tt +5 -3
- data/lib/rails/generators/rails/app/templates/Gemfile.tt +3 -1
- data/lib/rails/generators/rails/app/templates/config/ci.rb.tt +4 -0
- data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +3 -0
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +3 -0
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +2 -14
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_1.rb.tt +27 -0
- data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +7 -3
- data/lib/rails/generators/rails/authentication/authentication_generator.rb +0 -9
- data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt +3 -1
- data/lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt +3 -1
- data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +1 -1
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +1 -1
- data/lib/rails/generators/rails/plugin/plugin_generator.rb +1 -0
- data/lib/rails/generators/rails/plugin/templates/Rakefile.tt +0 -4
- data/lib/rails/generators/test_unit/authentication/authentication_generator.rb +12 -0
- data/lib/rails/generators/{rails → test_unit}/authentication/templates/test/test_helpers/session_test_helper.rb.tt +6 -2
- data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +4 -2
- data/lib/rails/info_controller.rb +2 -2
- data/lib/rails/tasks/statistics.rake +3 -21
- data/lib/rails/tasks.rb +1 -3
- data/lib/rails/templates/rails/mailers/email.html.erb +1 -1
- data/lib/rails/templates/rails/welcome/index.html.erb +2 -2
- metadata +12 -13
- data/lib/rails/console/methods.rb +0 -7
- /data/lib/rails/generators/{rails → test_unit}/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2c7cc136ad7a247e9749b90f452d24015e122513e375466e8b2ed7be469794b
|
4
|
+
data.tar.gz: cebd00d49ce9eac86e7e9c41fc2848de4d32e82a01a5243292847bef4843213f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59051d108c5fea0371db87c4f6685a8a5caad22abbd2d6208829b7b00dd67318476f2dafad6a4233b37e42b79ef64bad9e327cb5825c66953e94d3f20697295c
|
7
|
+
data.tar.gz: cccc101d3a4183542414fd7f78a11d25c88a141216eaff1dbe1f03a4e8f1a80e25ad6abac2cb02518b6fa08ece7e478ffddd3901be2843bdbe2b0c051324179c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,61 @@
|
|
1
|
+
## Rails 8.1.0.rc1 (October 15, 2025) ##
|
2
|
+
|
3
|
+
* Suggest `bin/rails action_text:install` from Action Dispatch error page
|
4
|
+
|
5
|
+
*Sean Doyle*
|
6
|
+
|
7
|
+
* Remove deprecated `STATS_DIRECTORIES`.
|
8
|
+
|
9
|
+
*Rafael Mendonça França*
|
10
|
+
|
11
|
+
* Remove deprecated `bin/rake stats` command.
|
12
|
+
|
13
|
+
*Rafael Mendonça França*
|
14
|
+
|
15
|
+
* Remove deprecated `rails/console/methods.rb` file.
|
16
|
+
|
17
|
+
*Rafael Mendonça França*
|
18
|
+
|
19
|
+
* Don't generate system tests by default.
|
20
|
+
|
21
|
+
Rails scaffold generator will no longer generate system tests by default. To enable this pass `--system-tests=true` or generate them with `bin/rails generate system_test name_of_test`.
|
22
|
+
|
23
|
+
*Eileen M. Uchitelle*
|
24
|
+
|
25
|
+
* Optionally skip bundler-audit.
|
26
|
+
|
27
|
+
Skips adding the `bin/bundler-audit` & `config/bundler-audit.yml` if the gem is not installed when `bin/rails app:update` runs.
|
28
|
+
|
29
|
+
Passes an option to `--skip-bundler-audit` when new apps are generated & adds that same option to the `--minimal` generator flag.
|
30
|
+
|
31
|
+
*Jill Klang*
|
32
|
+
|
33
|
+
* Show engine routes in `/rails/info/routes` as well.
|
34
|
+
|
35
|
+
*Petrik de Heus*
|
36
|
+
|
37
|
+
* Exclude `asset_path` configuration from Kamal `deploy.yml` for API applications.
|
38
|
+
|
39
|
+
API applications don't serve assets, so the `asset_path` configuration in `deploy.yml`
|
40
|
+
is not needed and can cause 404 errors on in-flight requests. The asset_path is now
|
41
|
+
only included for regular Rails applications that serve assets.
|
42
|
+
|
43
|
+
*Saiqul Haq*
|
44
|
+
|
45
|
+
* Reverted the incorrect default `config.public_file_server.headers` config.
|
46
|
+
|
47
|
+
If you created a new application using Rails `8.1.0.beta1`, make sure to regenerate
|
48
|
+
`config/environments/production.rb`, or to manually edit the `config.public_file_server.headers`
|
49
|
+
configuration to just be:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
# Cache assets for far-future expiry since they are all digest stamped.
|
53
|
+
config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" }
|
54
|
+
```
|
55
|
+
|
56
|
+
*Jean Boussier*
|
57
|
+
|
58
|
+
|
1
59
|
## Rails 8.1.0.beta1 (September 04, 2025) ##
|
2
60
|
|
3
61
|
* Add command `rails credentials:fetch PATH` to get the value of a credential from the credentials file.
|
@@ -73,7 +73,7 @@ module Rails
|
|
73
73
|
|
74
74
|
initializer :initialize_event_reporter, group: :all do
|
75
75
|
Rails.event.raise_on_error = config.consider_all_requests_local
|
76
|
-
Rails.event.debug_mode =
|
76
|
+
Rails.event.debug_mode = Rails.env.development?
|
77
77
|
end
|
78
78
|
|
79
79
|
# Initialize cache early in the stack so railties can make use of it.
|
@@ -117,10 +117,6 @@ module Rails
|
|
117
117
|
action_controller.forgery_protection_origin_check = true
|
118
118
|
end
|
119
119
|
|
120
|
-
if respond_to?(:active_support)
|
121
|
-
active_support.to_time_preserves_timezone = :offset
|
122
|
-
end
|
123
|
-
|
124
120
|
if respond_to?(:active_record)
|
125
121
|
active_record.belongs_to_required_by_default = true
|
126
122
|
end
|
@@ -267,7 +263,7 @@ module Rails
|
|
267
263
|
end
|
268
264
|
|
269
265
|
if respond_to?(:action_controller)
|
270
|
-
action_controller.
|
266
|
+
action_controller.action_on_open_redirect = :raise
|
271
267
|
action_controller.wrap_parameters_by_default = true
|
272
268
|
end
|
273
269
|
when "7.1"
|
@@ -339,10 +335,6 @@ module Rails
|
|
339
335
|
when "8.0"
|
340
336
|
load_defaults "7.2"
|
341
337
|
|
342
|
-
if respond_to?(:active_support)
|
343
|
-
active_support.to_time_preserves_timezone = :zone
|
344
|
-
end
|
345
|
-
|
346
338
|
if respond_to?(:action_dispatch)
|
347
339
|
action_dispatch.strict_freshness = true
|
348
340
|
end
|
@@ -365,6 +357,10 @@ module Rails
|
|
365
357
|
active_record.raise_on_missing_required_finder_order_columns = true
|
366
358
|
end
|
367
359
|
|
360
|
+
if respond_to?(:active_support)
|
361
|
+
active_support.escape_js_separators_in_json = false
|
362
|
+
end
|
363
|
+
|
368
364
|
if respond_to?(:action_view)
|
369
365
|
action_view.render_tracker = :ruby
|
370
366
|
end
|
@@ -42,8 +42,11 @@ module Rails
|
|
42
42
|
|
43
43
|
HEADERS = { lines: " Lines", code_lines: " LOC", classes: "Classes", methods: "Methods" }
|
44
44
|
|
45
|
+
PATTERN = /^(?!\.).*?\.(rb|js|ts|css|scss|coffee|rake|erb)$/
|
46
|
+
|
45
47
|
class_attribute :directories, default: DIRECTORIES
|
46
48
|
class_attribute :test_types, default: TEST_TYPES
|
49
|
+
class_attribute :pattern, default: PATTERN
|
47
50
|
|
48
51
|
# Add directories to the output of the <tt>bin/rails stats</tt> command.
|
49
52
|
#
|
@@ -81,7 +84,7 @@ module Rails
|
|
81
84
|
Hash[@pairs.map { |pair| [pair.first, calculate_directory_statistics(pair.last)] }]
|
82
85
|
end
|
83
86
|
|
84
|
-
def calculate_directory_statistics(directory, pattern =
|
87
|
+
def calculate_directory_statistics(directory, pattern = self.class.pattern)
|
85
88
|
stats = Rails::CodeStatisticsCalculator.new
|
86
89
|
|
87
90
|
Dir.foreach(directory) do |file_name|
|
@@ -73,6 +73,7 @@ module Rails
|
|
73
73
|
skip_action_text: !defined?(ActionText::Engine),
|
74
74
|
skip_action_cable: !defined?(ActionCable::Engine),
|
75
75
|
skip_brakeman: skip_gem?("brakeman"),
|
76
|
+
skip_bundler_audit: skip_gem?("bundler-audit"),
|
76
77
|
skip_rubocop: skip_gem?("rubocop"),
|
77
78
|
skip_thruster: skip_gem?("thruster"),
|
78
79
|
skip_test: !defined?(Rails::TestUnitRailtie),
|
data/lib/rails/gem_version.rb
CHANGED
@@ -106,6 +106,9 @@ module Rails
|
|
106
106
|
class_option :skip_brakeman, type: :boolean, default: nil,
|
107
107
|
desc: "Skip brakeman setup"
|
108
108
|
|
109
|
+
class_option :skip_bundler_audit, type: :boolean, default: nil,
|
110
|
+
desc: "Skip bundler-audit setup"
|
111
|
+
|
109
112
|
class_option :skip_ci, type: :boolean, default: nil,
|
110
113
|
desc: "Skip GitHub CI files"
|
111
114
|
|
@@ -400,6 +403,10 @@ module Rails
|
|
400
403
|
options[:skip_brakeman]
|
401
404
|
end
|
402
405
|
|
406
|
+
def skip_bundler_audit?
|
407
|
+
options[:skip_bundler_audit]
|
408
|
+
end
|
409
|
+
|
403
410
|
def skip_ci?
|
404
411
|
options[:skip_ci]
|
405
412
|
end
|
@@ -657,6 +664,11 @@ module Rails
|
|
657
664
|
end
|
658
665
|
end
|
659
666
|
|
667
|
+
def rails_command(command, command_options = {})
|
668
|
+
command_options[:capture] = true if options[:quiet]
|
669
|
+
super
|
670
|
+
end
|
671
|
+
|
660
672
|
def bundle_install?
|
661
673
|
!(options[:skip_bundle] || options[:pretend])
|
662
674
|
end
|
@@ -109,7 +109,7 @@ module Rails
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def bin
|
112
|
-
exclude_pattern = Regexp.union([(/thrust/ if skip_thruster?), (/rubocop/ if skip_rubocop?), (/brakeman/ if skip_brakeman?)].compact)
|
112
|
+
exclude_pattern = Regexp.union([(/thrust/ if skip_thruster?), (/rubocop/ if skip_rubocop?), (/brakeman/ if skip_brakeman?), (/bundler-audit/ if skip_bundler_audit?)].compact)
|
113
113
|
directory "bin", { exclude_pattern: exclude_pattern } do |content|
|
114
114
|
"#{shebang}\n" + content
|
115
115
|
end
|
@@ -127,8 +127,8 @@ module Rails
|
|
127
127
|
template "routes.rb" unless options[:update]
|
128
128
|
template "application.rb"
|
129
129
|
template "environment.rb"
|
130
|
-
template "bundler-audit.yml"
|
131
|
-
template "cable.yml" unless options[:update] ||
|
130
|
+
template "bundler-audit.yml" unless skip_bundler_audit?
|
131
|
+
template "cable.yml" unless options[:update] || skip_action_cable?
|
132
132
|
template "ci.rb"
|
133
133
|
template "puma.rb"
|
134
134
|
template "storage.yml" unless options[:update] || skip_active_storage?
|
@@ -153,7 +153,7 @@ module Rails
|
|
153
153
|
|
154
154
|
config
|
155
155
|
|
156
|
-
if !
|
156
|
+
if !skip_action_cable? && !action_cable_config_exist
|
157
157
|
template "config/cable.yml"
|
158
158
|
end
|
159
159
|
|
@@ -177,7 +177,7 @@ module Rails
|
|
177
177
|
remove_file "config/initializers/cors.rb"
|
178
178
|
end
|
179
179
|
|
180
|
-
if !bundle_audit_config_exist
|
180
|
+
if !skip_bundler_audit? && !bundle_audit_config_exist
|
181
181
|
template "config/bundler-audit.yml"
|
182
182
|
end
|
183
183
|
|
@@ -317,6 +317,7 @@ module Rails
|
|
317
317
|
:skip_active_storage,
|
318
318
|
:skip_bootsnap,
|
319
319
|
:skip_brakeman,
|
320
|
+
:skip_bundler_audit,
|
320
321
|
:skip_ci,
|
321
322
|
:skip_dev_gems,
|
322
323
|
:skip_docker,
|
@@ -65,7 +65,8 @@ COPY Gemfile Gemfile.lock vendor ./
|
|
65
65
|
|
66
66
|
RUN bundle install && \
|
67
67
|
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git<% if depend_on_bootsnap? -%> && \
|
68
|
-
|
68
|
+
# -j 1 disable parallel compilation to avoid a QEMU bug: https://github.com/rails/bootsnap/issues/495
|
69
|
+
bundle exec bootsnap precompile -j 1 --gemfile<% end %>
|
69
70
|
|
70
71
|
<% if using_node? -%>
|
71
72
|
# Install node modules
|
@@ -83,8 +84,9 @@ RUN bun install --frozen-lockfile
|
|
83
84
|
COPY . .
|
84
85
|
|
85
86
|
<% if depend_on_bootsnap? -%>
|
86
|
-
# Precompile bootsnap code for faster boot times
|
87
|
-
|
87
|
+
# Precompile bootsnap code for faster boot times.
|
88
|
+
# -j 1 disable parallel compilation to avoid a QEMU bug: https://github.com/rails/bootsnap/issues/495
|
89
|
+
RUN bundle exec bootsnap precompile -j 1 app/ lib/
|
88
90
|
|
89
91
|
<% end -%>
|
90
92
|
<% unless dockerfile_binfile_fixups.empty? -%>
|
@@ -42,7 +42,7 @@ gem "thruster", require: false
|
|
42
42
|
<% unless skip_active_storage? -%>
|
43
43
|
|
44
44
|
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
|
45
|
-
|
45
|
+
gem "image_processing", "~> 1.2"
|
46
46
|
<% end -%>
|
47
47
|
<%- if options.api? -%>
|
48
48
|
|
@@ -54,9 +54,11 @@ gem "thruster", require: false
|
|
54
54
|
group :development, :test do
|
55
55
|
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
56
56
|
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
|
57
|
+
<%- unless options.skip_bundler_audit? -%>
|
57
58
|
|
58
59
|
# Audits gems for known security defects (use config/bundler-audit.yml to ignore issues)
|
59
60
|
gem "bundler-audit", require: false
|
61
|
+
<%- end -%>
|
60
62
|
<%- unless options.skip_brakeman? -%>
|
61
63
|
|
62
64
|
# Static analysis for security vulnerabilities [https://brakemanscanner.org/]
|
@@ -6,7 +6,9 @@ CI.run do
|
|
6
6
|
step "Style: Ruby", "bin/rubocop"
|
7
7
|
<% end -%>
|
8
8
|
|
9
|
+
<% unless options.skip_bundler_audit? -%>
|
9
10
|
step "Security: Gem audit", "bin/bundler-audit"
|
11
|
+
<% end -%>
|
10
12
|
<% if using_node? -%>
|
11
13
|
step "Security: Yarn vulnerability audit", "yarn audit"
|
12
14
|
<% end -%>
|
@@ -22,7 +24,9 @@ CI.run do
|
|
22
24
|
step "Tests: Rails", "bin/rails test"
|
23
25
|
step "Tests: System", "bin/rails test:system"
|
24
26
|
<% end -%>
|
27
|
+
<% unless options.skip_active_record? -%>
|
25
28
|
step "Tests: Seeds", "env RAILS_ENV=test bin/rails db:seed:replant"
|
29
|
+
<% end -%>
|
26
30
|
|
27
31
|
# Optional: set a green GitHub commit status to unblock PR merge.
|
28
32
|
# Requires the `gh` CLI and `gh extension install basecamp/gh-signoff`.
|
@@ -80,11 +80,14 @@ volumes:
|
|
80
80
|
- "<%= app_name %>_storage:/rails/storage"
|
81
81
|
|
82
82
|
<% end -%>
|
83
|
+
<% unless options.api? -%>
|
83
84
|
# Bridge fingerprinted assets, like JS and CSS, between versions to avoid
|
84
85
|
# hitting 404 on in-flight requests. Combines all files from new and old
|
85
86
|
# version inside the asset_path.
|
86
87
|
asset_path: /rails/public/assets
|
87
88
|
|
89
|
+
<% end -%>
|
90
|
+
|
88
91
|
# Configure the image builder.
|
89
92
|
builder:
|
90
93
|
arch: amd64
|
@@ -65,6 +65,9 @@ Rails.application.configure do
|
|
65
65
|
config.active_job.verbose_enqueue_logs = true
|
66
66
|
|
67
67
|
<%- end -%>
|
68
|
+
# Highlight code that triggered redirect in logs.
|
69
|
+
config.action_dispatch.verbose_redirect_logs = true
|
70
|
+
|
68
71
|
<%- unless options[:skip_asset_pipeline] -%>
|
69
72
|
# Suppress logger output for asset requests.
|
70
73
|
config.assets.quiet = true
|
@@ -17,20 +17,8 @@ Rails.application.configure do
|
|
17
17
|
config.action_controller.perform_caching = true
|
18
18
|
<%- end -%>
|
19
19
|
|
20
|
-
# Cache
|
21
|
-
|
22
|
-
config.public_file_server.headers = {
|
23
|
-
"cache-control" => lambda do |path, _|
|
24
|
-
if path.start_with?("/assets/")
|
25
|
-
# Files in /assets/ are expected to be fully immutable.
|
26
|
-
# If the content change the URL too.
|
27
|
-
"public, immutable, max-age=#{1.year.to_i}"
|
28
|
-
else
|
29
|
-
# For anything else we cache for 1 minute.
|
30
|
-
"public, max-age=#{1.minute.to_i}, stale-while-revalidate=#{5.minutes.to_i}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
}
|
20
|
+
# Cache assets for far-future expiry since they are all digest stamped.
|
21
|
+
config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" }
|
34
22
|
|
35
23
|
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
|
36
24
|
# config.asset_host = "http://assets.example.com"
|
data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_1.rb.tt
CHANGED
@@ -27,6 +27,14 @@
|
|
27
27
|
#++
|
28
28
|
# Rails.configuration.action_controller.escape_json_responses = false
|
29
29
|
|
30
|
+
###
|
31
|
+
# Skips escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON.
|
32
|
+
#
|
33
|
+
# Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019.
|
34
|
+
# As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset.
|
35
|
+
#++
|
36
|
+
# Rails.configuration.active_support.escape_js_separators_in_json = false
|
37
|
+
|
30
38
|
###
|
31
39
|
# Raises an error when order dependent finder methods (e.g. `#first`, `#second`) are called without `order` values
|
32
40
|
# on the relation, and the model does not have any order columns (`implicit_order_column`, `query_constraints`, or
|
@@ -52,6 +60,25 @@
|
|
52
60
|
#++
|
53
61
|
# Rails.configuration.action_controller.action_on_path_relative_redirect = :raise
|
54
62
|
|
63
|
+
###
|
64
|
+
# Controls how Rails handles open redirect vulnerabilities.
|
65
|
+
# When set to `:raise`, Rails will raise an `ActionController::Redirecting::UnsafeRedirectError`
|
66
|
+
# for redirects to external hosts, which helps prevent open redirect attacks.
|
67
|
+
#
|
68
|
+
# This configuration replaces the deprecated `raise_on_open_redirects` setting, providing
|
69
|
+
# the ability for large codebases to safely turn on the protection (after monitoring it with :log/:notifications)
|
70
|
+
#
|
71
|
+
# Example:
|
72
|
+
# redirect_to params[:redirect_url] # May raise UnsafeRedirectError if URL is external
|
73
|
+
# redirect_to "http://evil.com" # Raises UnsafeRedirectError
|
74
|
+
# redirect_to "/safe/path" # Works correctly (internal URL)
|
75
|
+
# redirect_to "http://evil.com", allow_other_host: true # Works (explicitly allowed)
|
76
|
+
#
|
77
|
+
# Applications that want to allow these redirects can set the config to `:log` (previous default)
|
78
|
+
# to only log warnings, or `:notify` to send ActiveSupport notifications for monitoring.
|
79
|
+
#
|
80
|
+
#++
|
81
|
+
# Rails.configuration.action_controller.action_on_open_redirect = :raise
|
55
82
|
###
|
56
83
|
# Use a Ruby parser to track dependencies between Action View templates
|
57
84
|
#++
|
@@ -6,7 +6,7 @@ on:
|
|
6
6
|
branches: [ <%= user_default_branch %> ]
|
7
7
|
|
8
8
|
jobs:
|
9
|
-
<%- unless skip_brakeman? -%>
|
9
|
+
<%- unless skip_brakeman? && skip_bundler_audit? -%>
|
10
10
|
scan_ruby:
|
11
11
|
runs-on: ubuntu-latest
|
12
12
|
|
@@ -19,11 +19,15 @@ jobs:
|
|
19
19
|
with:
|
20
20
|
bundler-cache: true
|
21
21
|
|
22
|
+
<%- unless skip_brakeman? %>
|
22
23
|
- name: Scan for common Rails security vulnerabilities using static analysis
|
23
24
|
run: bin/brakeman --no-pager
|
25
|
+
<% end %>
|
24
26
|
|
27
|
+
<%- unless skip_bundler_audit? -%>
|
25
28
|
- name: Scan for known security vulnerabilities in gems used
|
26
29
|
run: bin/bundler-audit
|
30
|
+
<% end %>
|
27
31
|
|
28
32
|
<% end -%>
|
29
33
|
<%- if using_importmap? -%>
|
@@ -142,7 +146,7 @@ jobs:
|
|
142
146
|
<%- end -%>
|
143
147
|
# RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
|
144
148
|
# REDIS_URL: redis://localhost:6379/0
|
145
|
-
run: bin/rails db:test:prepare test
|
149
|
+
run: bin/rails <%= "db:test:prepare " unless skip_active_record? %>test
|
146
150
|
<%- unless options[:api] || options[:skip_system_test] -%>
|
147
151
|
|
148
152
|
system-test:
|
@@ -215,7 +219,7 @@ jobs:
|
|
215
219
|
<%- end -%>
|
216
220
|
# RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
|
217
221
|
# REDIS_URL: redis://localhost:6379/0
|
218
|
-
run: bin/rails db:test:prepare test:system
|
222
|
+
run: bin/rails <%= "db:test:prepare " unless skip_active_record? %>test:system
|
219
223
|
|
220
224
|
- name: Keep screenshots from failed system tests
|
221
225
|
uses: actions/upload-artifact@v4
|
@@ -30,11 +30,7 @@ module Rails
|
|
30
30
|
|
31
31
|
template "app/views/passwords_mailer/reset.html.erb"
|
32
32
|
template "app/views/passwords_mailer/reset.text.erb"
|
33
|
-
|
34
|
-
template "test/mailers/previews/passwords_mailer_preview.rb"
|
35
33
|
end
|
36
|
-
|
37
|
-
template "test/test_helpers/session_test_helper.rb"
|
38
34
|
end
|
39
35
|
|
40
36
|
def configure_application_controller
|
@@ -60,11 +56,6 @@ module Rails
|
|
60
56
|
generate "migration", "CreateSessions", "user:references ip_address:string user_agent:string", "--force"
|
61
57
|
end
|
62
58
|
|
63
|
-
def configure_test_helper
|
64
|
-
inject_into_file "test/test_helper.rb", "require_relative \"test_helpers/session_test_helper\"\n", after: "require \"rails/test_help\"\n"
|
65
|
-
inject_into_class "test/test_helper.rb", "TestCase", " include SessionTestHelper\n"
|
66
|
-
end
|
67
|
-
|
68
59
|
hook_for :test_framework
|
69
60
|
end
|
70
61
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
<p>
|
2
|
-
You can reset your password
|
2
|
+
You can reset your password on
|
3
3
|
<%%= link_to "this password reset page", edit_password_url(@user.password_reset_token) %>.
|
4
|
+
|
5
|
+
This link will expire in <%%= distance_of_time_in_words(0, @user.password_reset_token_expires_in) %>.
|
4
6
|
</p>
|
@@ -1,2 +1,4 @@
|
|
1
|
-
You can reset your password
|
1
|
+
You can reset your password on
|
2
2
|
<%%= edit_password_url(@user.password_reset_token) %>
|
3
|
+
|
4
|
+
This link will expire in <%%= distance_of_time_in_words(0, @user.password_reset_token_expires_in) %>.
|
@@ -112,7 +112,7 @@ module Rails
|
|
112
112
|
|
113
113
|
@features["ghcr.io/rails/devcontainer/features/activestorage"] = {} if options[:active_storage]
|
114
114
|
@features["ghcr.io/devcontainers/features/node:1"] = {} if options[:node]
|
115
|
-
@features["ghcr.io/devcontainers/features/docker-outside-of-docker:1"] = {} if options[:kamal]
|
115
|
+
@features["ghcr.io/devcontainers/features/docker-outside-of-docker:1"] = { moby: false } if options[:kamal]
|
116
116
|
|
117
117
|
@features.merge!(database.feature) if database.feature
|
118
118
|
|
@@ -8,7 +8,7 @@
|
|
8
8
|
|
9
9
|
// Features to add to the dev container. More info: https://containers.dev/features.
|
10
10
|
"features": {
|
11
|
-
<%= features.map { |key, value| "\"#{key}\": #{value.
|
11
|
+
<%= features.map { |key, value| "\"#{key}\": #{value.to_json}" }.join(",\n ") %>
|
12
12
|
},
|
13
13
|
|
14
14
|
<%- if !container_env.empty? -%>
|
@@ -4,10 +4,6 @@ require "bundler/setup"
|
|
4
4
|
APP_RAKEFILE = File.expand_path("<%= dummy_path -%>/Rakefile", __dir__)
|
5
5
|
load "rails/tasks/engine.rake"
|
6
6
|
<% end -%>
|
7
|
-
<% if engine? -%>
|
8
|
-
|
9
|
-
load "rails/tasks/statistics.rake"
|
10
|
-
<% end -%>
|
11
7
|
<% unless options[:skip_gemspec] -%>
|
12
8
|
|
13
9
|
require "bundler/gem_tasks"
|
@@ -14,6 +14,18 @@ module TestUnit # :nodoc:
|
|
14
14
|
template "test/controllers/sessions_controller_test.rb"
|
15
15
|
template "test/controllers/passwords_controller_test.rb"
|
16
16
|
end
|
17
|
+
|
18
|
+
def create_mailer_preview_files
|
19
|
+
template "test/mailers/previews/passwords_mailer_preview.rb" if defined?(ActionMailer::Railtie)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_test_helper_files
|
23
|
+
template "test/test_helpers/session_test_helper.rb"
|
24
|
+
end
|
25
|
+
|
26
|
+
def configure_test_helper
|
27
|
+
inject_into_file "test/test_helper.rb", "require_relative \"test_helpers/session_test_helper\"\n", after: "require \"rails/test_help\"\n"
|
28
|
+
end
|
17
29
|
end
|
18
30
|
end
|
19
31
|
end
|
@@ -4,12 +4,16 @@ module SessionTestHelper
|
|
4
4
|
|
5
5
|
ActionDispatch::TestRequest.create.cookie_jar.tap do |cookie_jar|
|
6
6
|
cookie_jar.signed[:session_id] = Current.session.id
|
7
|
-
cookies[
|
7
|
+
cookies["session_id"] = cookie_jar[:session_id]
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
def sign_out
|
12
12
|
Current.session&.destroy!
|
13
|
-
cookies.delete(
|
13
|
+
cookies.delete("session_id")
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
18
|
+
include SessionTestHelper
|
19
|
+
end
|
@@ -14,7 +14,7 @@ module TestUnit # :nodoc:
|
|
14
14
|
desc: "Generate API functional tests"
|
15
15
|
|
16
16
|
class_option :system_tests, type: :string,
|
17
|
-
desc: "
|
17
|
+
desc: "Generate system test files (set to 'true' to enable)"
|
18
18
|
|
19
19
|
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
20
20
|
|
@@ -23,7 +23,9 @@ module TestUnit # :nodoc:
|
|
23
23
|
template template_file,
|
24
24
|
File.join("test/controllers", controller_class_path, "#{controller_file_name}_controller_test.rb")
|
25
25
|
|
26
|
-
if
|
26
|
+
# Generate system tests if this isn't an API only app and the system
|
27
|
+
# tests option is true
|
28
|
+
if !options.api? && options[:system_tests] == "true"
|
27
29
|
template "system_test.rb", File.join("test/system", class_path, "#{file_name.pluralize}_test.rb")
|
28
30
|
end
|
29
31
|
end
|
@@ -27,7 +27,7 @@ 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(
|
30
|
+
@routes_inspector = ActionDispatch::Routing::RoutesInspector.new(Rails.application.routes.routes)
|
31
31
|
@page_title = "Routes"
|
32
32
|
end
|
33
33
|
end
|
@@ -46,7 +46,7 @@ class Rails::InfoController < Rails::ApplicationController # :nodoc:
|
|
46
46
|
normalized_path = ("/" + query).squeeze("/")
|
47
47
|
query_without_url_or_path_suffix = query.gsub(/(\w)(_path$)/, '\1').gsub(/(\w)(_url$)/, '\1')
|
48
48
|
|
49
|
-
|
49
|
+
Rails.application.routes.routes.filter_map do |route|
|
50
50
|
route_wrapper = ActionDispatch::Routing::RouteWrapper.new(route)
|
51
51
|
|
52
52
|
if exact_match
|
@@ -1,23 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
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
@@ -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">
|
@@ -95,7 +95,7 @@
|
|
95
95
|
<body>
|
96
96
|
<nav>
|
97
97
|
<a href="https://rubyonrails.org" target="_blank">
|
98
|
-
<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==" />
|
99
99
|
</a>
|
100
100
|
</nav>
|
101
101
|
|
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.1.0.
|
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.1.0.
|
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.1.0.
|
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.1.0.
|
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.1.0.
|
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.1.0.
|
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.1.0.
|
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
|
@@ -346,8 +345,6 @@ files:
|
|
346
345
|
- lib/rails/generators/rails/authentication/templates/app/models/user.rb.tt
|
347
346
|
- lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.html.erb.tt
|
348
347
|
- lib/rails/generators/rails/authentication/templates/app/views/passwords_mailer/reset.text.erb.tt
|
349
|
-
- lib/rails/generators/rails/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt
|
350
|
-
- lib/rails/generators/rails/authentication/templates/test/test_helpers/session_test_helper.rb.tt
|
351
348
|
- lib/rails/generators/rails/benchmark/USAGE
|
352
349
|
- lib/rails/generators/rails/benchmark/benchmark_generator.rb
|
353
350
|
- lib/rails/generators/rails/benchmark/templates/benchmark.rb.tt
|
@@ -434,7 +431,9 @@ files:
|
|
434
431
|
- lib/rails/generators/test_unit/authentication/templates/test/controllers/passwords_controller_test.rb.tt
|
435
432
|
- lib/rails/generators/test_unit/authentication/templates/test/controllers/sessions_controller_test.rb
|
436
433
|
- lib/rails/generators/test_unit/authentication/templates/test/fixtures/users.yml.tt
|
434
|
+
- lib/rails/generators/test_unit/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb.tt
|
437
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
|
438
437
|
- lib/rails/generators/test_unit/controller/controller_generator.rb
|
439
438
|
- lib/rails/generators/test_unit/controller/templates/functional_test.rb.tt
|
440
439
|
- lib/rails/generators/test_unit/generator/generator_generator.rb
|
@@ -509,10 +508,10 @@ licenses:
|
|
509
508
|
- MIT
|
510
509
|
metadata:
|
511
510
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
512
|
-
changelog_uri: https://github.com/rails/rails/blob/v8.1.0.
|
513
|
-
documentation_uri: https://api.rubyonrails.org/v8.1.0.
|
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/
|
514
513
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
515
|
-
source_code_uri: https://github.com/rails/rails/tree/v8.1.0.
|
514
|
+
source_code_uri: https://github.com/rails/rails/tree/v8.1.0.rc1/railties
|
516
515
|
rubygems_mfa_required: 'true'
|
517
516
|
rdoc_options:
|
518
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
|