Upgrading rails 7 to 8
Breaking7.2.4 → 8.1.4Breaking48Security17Platform2Deprecated25New229Changed188Fixed384Other7
SecurityLimits the size of strings ActiveModel::Type::Integer coerces with to_i to prevent a DoS vector.Advisory ↗
BreakingUpgrade verdict
48 breaking changes and 2 platform requirement changes and 17 security fixes.
In plain terms
- Code that passed a Time object to Time#since no longer works and must be updated.
- Benchmark.ms is no longer part of Active Support; use the benchmark gem instead.
- Adding a Time to an ActiveSupport::TimeWithZone no longer works.
- to_time now always keeps the receiver's timezone instead of optionally using the system local time.
Must act Top 5 of 90 that need code or config changes
rails publishes an official migration guide for version 8. It covers more than the release notes do.
Upgrading from Rails 7.2 to Rails 8.0 ↗Ruby requirement changed in 8.0.0.beta1: >= 3.1.0 → >= 3.2.0.
What you must change
Breaking48
Removes deprecated support for passing a Time object to Time#since.
Time#sinceRemoves the deprecated Benchmark.ms method, now defined in the benchmark gem.
Benchmark.msRemoves deprecated addition of Time instances with ActiveSupport::TimeWithZone.
TimeActiveSupport::TimeWithZoneRemoves deprecated support for to_time preserving the system local time; it now always preserves the receiver timezone.
to_timeRemoves deprecated :unsigned_float and :unsigned_decimal column methods for MySQL.
:unsigned_float:unsigned_decimalRemoves deprecated :retries option for the SQLite3 adapter.
:retriesRaises ActiveRecord::MissingRequiredOrderError for order dependent finders without order values, enabled by a new Rails 8.1 framework default.
ActiveRecord::MissingRequiredOrderErrorfirstlastimplicit_order_columnquery_constraintsprimary_keyraise_on_missing_required_finder_order_columnsRemoves deprecated support to route to multiple paths.
Removes deprecated support for using semicolons as a query string separator.
ActionDispatch::QueryParser.each_pairRemoves deprecated support for skipping over leading brackets in parameter names in the parameter parser.
ActionDispatch::ParamBuilder.from_query_stringRemoves support for setting
ActiveJob::Base.enqueue_after_transaction_commit to :never, :always and :default.ActiveJob::Base.enqueue_after_transaction_commitRemoves the deprecated
Rails.application.config.active_job.enqueue_after_transaction_commit config.Rails.application.config.active_job.enqueue_after_transaction_commitRemoves the deprecated :azure storage service.
:azureRemoves deprecated STATS_DIRECTORIES.
STATS_DIRECTORIESRemoves the deprecated bin/rake stats command.
bin/rake statsRemoves the deprecated rails/console/methods.rb file.
rails/console/methods.rbRails no longer generates a bin/bundle binstub when creating new applications, since the mechanism is now part of Rubygem itself.
bin/bundleRemoves deprecated support for passing an array of strings to ActiveSupport::Deprecation#warn.
ActiveSupport::Deprecation#warnRemoves deprecated support for setting attr_internal_naming_format with a @ prefix.
attr_internal_naming_formatRemoves deprecated ActiveSupport::ProxyObject.
ActiveSupport::ProxyObjectRemoves deprecated support for setting ENV["SCHEMA_CACHE"].
SCHEMA_CACHERemoves deprecated support for passing a database name to cache_dump_filename.
cache_dump_filenameRemoves deprecated ActiveRecord::ConnectionAdapters::ConnectionPool#connection.
ActiveRecord::ConnectionAdapters::ConnectionPool#connectionRemoves deprecated config.active_record.sqlite3_deprecated_warning.
config.active_record.sqlite3_deprecated_warningRemoves deprecated config.active_record.warn_on_records_fetched_greater_than.
config.active_record.warn_on_records_fetched_greater_thanRemoves deprecated support for defining enum with keyword arguments.
enumRemoves deprecated support for finding database adapters not registered to Active Record.
Removes deprecated config.active_record.allow_deprecated_singular_associations_name.
config.active_record.allow_deprecated_singular_associations_nameRemoves deprecated config.active_record.commit_transaction_on_non_local_return.
config.active_record.commit_transaction_on_non_local_returnDeletes the deprecated constant ActiveRecord::ImmutableRelation.
ActiveRecord::ImmutableRelationRemoves deprecated support for passing content to void tag elements on the tag builder.
tagRemoves deprecated support for passing nil to the model: argument of form_with.
form_withRemoves Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality.
Rails.application.config.action_controller.allow_deprecated_parameters_hash_equalityRemoves deprecated config.active_job.use_big_decimal_serializer.
config.active_job.use_big_decimal_serializerRemoves deprecated support for extending the Rails console through Rails::ConsoleMethods.
Rails::ConsoleMethodsRemoves the deprecated file rails/console/helpers.
rails/console/helpersRemoves the deprecated file rails/console/app.
rails/console/appRemoves deprecated config.read_encrypted_secrets.
config.read_encrypted_secretsAlways clears CurrentAttributes instances, abandoning them at request end and creating new ones per request.
CurrentAttributesMakes :class_name invalid in polymorphic belongs_to associations.
belongs_toclass_nameRaises AbstractController::DoubleRenderError if head is called after rendering.
AbstractController::DoubleRenderErrorheadrenderA route pointing to a non-existing controller now returns a 500 instead of a 404.
Removes the deprecated internal
SuckerPunch adapter in favor of the adapter included with the sucker_punch gem.SuckerPunchMakes :class_name invalid in polymorphic belongs_to associations.
class_namebelongs_toRaises AbstractController::DoubleRenderError when head is called after rendering.
headAbstractController::DoubleRenderErrorRemoves the deprecated internal SuckerPunch adapter in favor of the adapter included with the sucker_punch gem.
SuckerPunchPrevents glob injection in DiskService#delete_prefixed by escaping glob metacharacters, breaking code that relied on glob expansion.
DiskService#delete_prefixedDir.globFixes HashWithIndifferentAccess#stringify_keys to stringify all keys, not just symbols.
ActiveSupport::HashWithIndifferentAccess#stringify_keysSecurity17
Limits the size of strings ActiveModel::Type::Integer coerces with to_i to prevent a DoS vector.
ActiveModel::Type::Integerto_iFilters the database password out of failed db: task command error messages.
Fixes possible XSS in DebugExceptions middleware.
DebugExceptionsRate limits password resets in the authentication generator to mitigate abuse from attackers spamming the password reset form.
Disables libvips unfuzzed image loaders and savers via Vips.block_untrusted(true) at boot, raising Vips::Error for affected transformations.
Vips.block_untrustedVips::Errorconfig.active_storage.variable_content_typesRejects scientific notation in NumberConverter.
NumberConverterFixes SafeBuffer#% to preserve unsafe status.
SafeBuffer#%Improves performance of NumberToDelimitedConverter.
NumberToDelimitedConverterSkips blank attribute names in tag helpers to avoid generating invalid HTML.
Filters user supplied metadata in DirectUploadController.
DirectUploadControllerAdds a configurable maximum streaming chunk size, defaulting to 100mb for blob byte ranges.
Limits range requests to a single range.
Prevents path traversal in DiskService; path_for raises InvalidKeyError for dot segments or paths outside the storage root.
DiskServiceDiskService#path_forInvalidKeyErrorDiskControllerArgumentErrorEncoding::CompatibilityErrorCalls inspect on ids in RecordNotFound error messages, addressing CVE-2025-55193.
RecordNotFoundRemoves dangerous transformations in Active Storage, addressing CVE-2025-24293.
Adds validation to content security policies to disallow spaces and semicolons.
Sets Regexp.timeout to 1 second by default to mitigate Regexp Denial-of-Service attacks.
Regexp.timeoutPlatform2
Raises minimum supported libvips to 8.13 and ruby-vips to 2.2.1, raising RuntimeError at boot when ruby-vips is installed and unmet.
libvipsruby-vipsRaises minimum supported libvips to 8.13 and ruby-vips to 2.2.1, raising RuntimeError at boot when ruby-vips is installed and either minimum is unmet.
RuntimeErrorDeprecations to plan for
Deprecated23
Deprecates config.active_support.to_time_preserves_timezone.
config.active_support.to_time_preserves_timezoneDeprecates String#mb_chars and ActiveSupport::Multibyte::Chars.
String#mb_charsActiveSupport::Multibyte::CharsDeprecates ActiveSupport::Configurable.
ActiveSupport::ConfigurableDeprecates signed_id_verifier_secret on model classes.
signed_id_verifier_secretsigned_id_verifierDeprecates using
insert_all/upsert_all with unpersisted records in associations, which are lost after the operation.insert_allupsert_allDeprecates
update_all with WITH, WITH RECURSIVE or DISTINCT, which were ignored; an error will be raised in a future release.update_alldelete_allDeprecates Rails.application.config.action_dispatch.ignore_leading_brackets.
Rails.application.config.action_dispatch.ignore_leading_bracketsDeprecates the built-in
sidekiq adapter; use the sidekiq gem's adapter with sidekiq 7.3.3 or later.sidekiqDeprecates String#mb_chars and ActiveSupport::Multibyte::Chars.
String#mb_charsActiveSupport::Multibyte::CharsDeprecates using insert_all/upsert_all with unpersisted records in associations.
insert_allupsert_allDeprecates using WITH, WITH RECURSIVE or DISTINCT with update_all; an error will be raised in a future release.
update_alldelete_allDeprecates the built-in sidekiq adapter in favor of the adapter shipped with sidekiq 7.3.3 or later.
sidekiqDeprecates the Benchmark.ms core extension as the benchmark gem becomes bundled in Ruby 3.5.
Benchmark.msDeprecates addition and since between two Time and ActiveSupport::TimeWithZone instances, to be removed in Rails 8.1.
TimeActiveSupport::TimeWithZonesinceDeprecates unsigned_float and unsigned_decimal short-hand column methods.
unsigned_floatunsigned_decimalDeprecates drawing routes with multiple paths to make routing faster.
with_optionsDeprecates sucker_punch as an adapter option.
sucker_punchadapter: asyncDeprecates ActiveStorage::Service::AzureStorageService.
ActiveStorage::Service::AzureStorageServiceDeprecates ::STATS_DIRECTORIES in favor of Rails::CodeStatistics.register_directory.
STATS_DIRECTORIESRails::CodeStatistics.register_directoryrails/code_statisticsDeprecates bin/rake stats in favor of bin/rails stats.
bin/rake statsbin/rails statsDeprecates the
Benchmark.ms core extension because the benchmark gem becomes bundled in Ruby 3.5.Benchmark.msDeprecates sucker_punch as an Active Job adapter option.
sucker_punchadapter: asyncDeprecates the ::STATS_DIRECTORIES constant in favor of Rails::CodeStatistics.register_directory.
STATS_DIRECTORIESRails::CodeStatistics.register_directory