In Rails 8, we can now mark Active Record associations as deprecated. This makes it easy to phase out old associations from our codebase, while still keeping them around to safely remove their usages. Whenever a deprecated association is used, whether by calling the association, executing a query that references it, or triggering a side‑effect like :dependent or :touch, Rails will alert us according to our chosen reporting mode.
Simply pass the deprecated: true
option when declaring an association.
class User < ApplicationRecord
has_many :meetings, deprecated: true
end
Now, every time the meeting association is invoked, we’ll get a deprecation warning in our logs.
> user.meetings
The association User#meetings is deprecated, the method meetings was invoked ((calendar):4:in '<main>')
> User.includes(:meetings).where(id: 1)
The association User#meetings is deprecated, referenced in query to preload records ()
> User.joins(:meetings).where(id: 1)
The association User#meetings is deprecated, referenced in query to join its table ()
We can deprecate any association type.
class Order < ApplicationRecord
# has_many
has_many :line_items, deprecated: true
# belongs_to
belongs_to :customer, deprecated: true
# has_one
has_one :profile, deprecated: true
# has_many through
has_many :archived_comments, through: :comments, deprecated: true
end
This feature supports three deprecation modes:
:warn
(default) Logs a warning to our Active Record logger.:raise
Raises an exception when the deprecated association is used.:notify
Emits an Active Support notification event with the key
deprecated_association.active_record
. This can be used to send notifications
to external services like Honeybadger etc. We can check the details about its
payload
here.Backtraces are disabled by default. If :backtrace
is true, :warn
mode will
include a clean backtrace in the message, and :notify
mode will have a
backtrace
key in the payload. Exceptions raised via :raise
mode will always
have a clean stack trace.
We can change the global default mode in an initializer.
# config/initializers/deprecated_associations.rb
ActiveRecord.deprecated_associations_options = {
mode: :warn, # :warn | :raise | :notify
backtrace: true # whether to include a cleaned backtrace
}
It can also be set at an environment level.
# config/environments/development.rb
Rails.application.configure do
config.active_record.deprecated_associations_options = { mode: :raise, backtrace: true }
end
# config/environments/production.rb
Rails.application.configure do
config.active_record.deprecated_associations_options = { mode: :warn, backtrace: true }
end
In large applications, it’s often hard to guarantee complete test coverage. Some association usages may only surface in production.
Deprecating an association first, lets us:
This new feature in Rails provides a clean and intuitive way to phase out our associations with deprecation warnings, making it easier to maintain and refactor large codebases.
This feature was merged recently, and will be released in the next Rails minor/patch version.
If this blog was helpful, check out our full blog archive.