Skip to content

Upgrading rails 7 to 8

Breaking7.2.4 → 8.1.4Breaking48Security17Platform2Deprecated25New229Changed188Fixed384Other7

BreakingUpgrade verdict

48 breaking changes and 2 platform requirement changes and 17 security fixes.

  • 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.
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.

Breaking48
Removes deprecated support for passing a Time object to Time#since.
Time#since
Removes the deprecated Benchmark.ms method, now defined in the benchmark gem.
Benchmark.ms
Removes deprecated addition of Time instances with ActiveSupport::TimeWithZone.
TimeActiveSupport::TimeWithZone
Removes deprecated support for to_time preserving the system local time; it now always preserves the receiver timezone.
to_time
Removes deprecated :unsigned_float and :unsigned_decimal column methods for MySQL.
:unsigned_float:unsigned_decimal
Removes deprecated :retries option for the SQLite3 adapter.
:retries
Raises 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_columns
Removes deprecated support to route to multiple paths.
Removes deprecated support for using semicolons as a query string separator.
ActionDispatch::QueryParser.each_pair
Removes deprecated support for skipping over leading brackets in parameter names in the parameter parser.
ActionDispatch::ParamBuilder.from_query_string
Removes support for setting ActiveJob::Base.enqueue_after_transaction_commit to :never, :always and :default.
ActiveJob::Base.enqueue_after_transaction_commit
Removes the deprecated Rails.application.config.active_job.enqueue_after_transaction_commit config.
Rails.application.config.active_job.enqueue_after_transaction_commit
Removes the deprecated :azure storage service.
:azure
Removes deprecated STATS_DIRECTORIES.
STATS_DIRECTORIES
Removes the deprecated bin/rake stats command.
bin/rake stats
Removes the deprecated rails/console/methods.rb file.
rails/console/methods.rb
Rails no longer generates a bin/bundle binstub when creating new applications, since the mechanism is now part of Rubygem itself.
bin/bundle
Removes deprecated support for passing an array of strings to ActiveSupport::Deprecation#warn.
ActiveSupport::Deprecation#warn
Removes deprecated support for setting attr_internal_naming_format with a @ prefix.
attr_internal_naming_format
Removes deprecated ActiveSupport::ProxyObject.
ActiveSupport::ProxyObject
Removes deprecated support for setting ENV["SCHEMA_CACHE"].
SCHEMA_CACHE
Removes deprecated support for passing a database name to cache_dump_filename.
cache_dump_filename
Removes deprecated ActiveRecord::ConnectionAdapters::ConnectionPool#connection.
ActiveRecord::ConnectionAdapters::ConnectionPool#connection
Removes deprecated config.active_record.sqlite3_deprecated_warning.
config.active_record.sqlite3_deprecated_warning
Removes deprecated config.active_record.warn_on_records_fetched_greater_than.
config.active_record.warn_on_records_fetched_greater_than
Removes deprecated support for defining enum with keyword arguments.
enum
Removes 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_name
Removes deprecated config.active_record.commit_transaction_on_non_local_return.
config.active_record.commit_transaction_on_non_local_return
Deletes the deprecated constant ActiveRecord::ImmutableRelation.
ActiveRecord::ImmutableRelation
Removes deprecated support for passing content to void tag elements on the tag builder.
tag
Removes deprecated support for passing nil to the model: argument of form_with.
form_with
Removes Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality.
Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality
Removes deprecated config.active_job.use_big_decimal_serializer.
config.active_job.use_big_decimal_serializer
Removes deprecated support for extending the Rails console through Rails::ConsoleMethods.
Rails::ConsoleMethods
Removes the deprecated file rails/console/helpers.
rails/console/helpers
Removes the deprecated file rails/console/app.
rails/console/app
Removes deprecated config.read_encrypted_secrets.
config.read_encrypted_secrets
Always clears CurrentAttributes instances, abandoning them at request end and creating new ones per request.
CurrentAttributes
Makes :class_name invalid in polymorphic belongs_to associations.
belongs_toclass_name
Raises AbstractController::DoubleRenderError if head is called after rendering.
AbstractController::DoubleRenderErrorheadrender
A 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.
SuckerPunch
Makes :class_name invalid in polymorphic belongs_to associations.
class_namebelongs_to
Raises AbstractController::DoubleRenderError when head is called after rendering.
headAbstractController::DoubleRenderError
Removes the deprecated internal SuckerPunch adapter in favor of the adapter included with the sucker_punch gem.
SuckerPunch
Prevents glob injection in DiskService#delete_prefixed by escaping glob metacharacters, breaking code that relied on glob expansion.
DiskService#delete_prefixedDir.glob
Fixes HashWithIndifferentAccess#stringify_keys to stringify all keys, not just symbols.
ActiveSupport::HashWithIndifferentAccess#stringify_keys
Security17
Limits the size of strings ActiveModel::Type::Integer coerces with to_i to prevent a DoS vector.
ActiveModel::Type::Integerto_i
Filters the database password out of failed db: task command error messages.
Fixes possible XSS in DebugExceptions middleware.
DebugExceptions
Rate 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_types
Rejects scientific notation in NumberConverter.
NumberConverter
Fixes SafeBuffer#% to preserve unsafe status.
SafeBuffer#%
Improves performance of NumberToDelimitedConverter.
NumberToDelimitedConverter
Skips blank attribute names in tag helpers to avoid generating invalid HTML.
Filters user supplied metadata in DirectUploadController.
DirectUploadController
Adds 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::CompatibilityError
Calls inspect on ids in RecordNotFound error messages, addressing CVE-2025-55193.
RecordNotFound
Removes 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.timeout
Platform2
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-vips
Raises 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.
RuntimeError
Deprecated23
Deprecates config.active_support.to_time_preserves_timezone.
config.active_support.to_time_preserves_timezone
Deprecates String#mb_chars and ActiveSupport::Multibyte::Chars.
String#mb_charsActiveSupport::Multibyte::Chars
Deprecates ActiveSupport::Configurable.
ActiveSupport::Configurable
Deprecates signed_id_verifier_secret on model classes.
signed_id_verifier_secretsigned_id_verifier
Deprecates using insert_all/upsert_all with unpersisted records in associations, which are lost after the operation.
insert_allupsert_all
Deprecates update_all with WITH, WITH RECURSIVE or DISTINCT, which were ignored; an error will be raised in a future release.
update_alldelete_all
Deprecates Rails.application.config.action_dispatch.ignore_leading_brackets.
Rails.application.config.action_dispatch.ignore_leading_brackets
Deprecates the built-in sidekiq adapter; use the sidekiq gem's adapter with sidekiq 7.3.3 or later.
sidekiq
Deprecates String#mb_chars and ActiveSupport::Multibyte::Chars.
String#mb_charsActiveSupport::Multibyte::Chars
Deprecates using insert_all/upsert_all with unpersisted records in associations.
insert_allupsert_all
Deprecates using WITH, WITH RECURSIVE or DISTINCT with update_all; an error will be raised in a future release.
update_alldelete_all
Deprecates the built-in sidekiq adapter in favor of the adapter shipped with sidekiq 7.3.3 or later.
sidekiq
Deprecates the Benchmark.ms core extension as the benchmark gem becomes bundled in Ruby 3.5.
Benchmark.ms
Deprecates addition and since between two Time and ActiveSupport::TimeWithZone instances, to be removed in Rails 8.1.
TimeActiveSupport::TimeWithZonesince
Deprecates unsigned_float and unsigned_decimal short-hand column methods.
unsigned_floatunsigned_decimal
Deprecates drawing routes with multiple paths to make routing faster.
with_options
Deprecates sucker_punch as an adapter option.
sucker_punchadapter: async
Deprecates ActiveStorage::Service::AzureStorageService.
ActiveStorage::Service::AzureStorageService
Deprecates ::STATS_DIRECTORIES in favor of Rails::CodeStatistics.register_directory.
STATS_DIRECTORIESRails::CodeStatistics.register_directoryrails/code_statistics
Deprecates bin/rake stats in favor of bin/rails stats.
bin/rake statsbin/rails stats
Deprecates the Benchmark.ms core extension because the benchmark gem becomes bundled in Ruby 3.5.
Benchmark.ms
Deprecates sucker_punch as an Active Job adapter option.
sucker_punchadapter: async
Deprecates the ::STATS_DIRECTORIES constant in favor of Rails::CodeStatistics.register_directory.
STATS_DIRECTORIESRails::CodeStatistics.register_directory