Rails 8.1: Deprecated Associations and How to Fix Them
Rails 8.1 includes support for marking associations as deprecated right in your models. In this post, I’ll explain how the feature works, why it matters, and how you can use it to safely remove outdated associations from your application.
Overview of Deprecated Associations in Rails 8.1
Rails 8.1 lets you explicitly mark outdated or obsolete associations as deprecated. If your codebase includes association tables or relationships that are no longer valid, you can flag them by adding the deprecated: true option to the association definition:
has_many :blogs, deprecated: true
Keep in mind that you need to mark both sides of a relationship as deprecated. Marking only one (like has_many) isn’t enough. To fully deprecate a relationship, add deprecated: true to both related associations. For example:
has_many :blogs, deprecated: true
belongs_to :author, deprecated: true
Once an association is marked as deprecated, Rails will show a warning whenever it’s used:
# Example output when accessing deprecated associations:
Author.first.blogs
#The association Author#blogs is deprecated, the method blogs was invoked ((irb):10:in '<main>')
Blog.first.author
#The association Blog#author is deprecated, the method author was invoked ((irb):11:in '<main>')
This helps you and your team avoid using old associations by mistake, and makes it easier to find code that still uses them.
You can see the entire change on the Rails 8.1 Deprecated Associations PR .
How to change the reporting mode
Reporting mode is set globally, not per association. You can configure it in your application config:
config.active_record.deprecated_associations_options = { mode: :raise, backtrace: true }
Valid modes are:
:warn(default): logs a warning when the association is used:raise: raises an error:notify: sends a notification (for custom handling)
Set backtrace: true to include a clean backtrace in warnings, notifications, or errors. This helps you track down where deprecated associations are being used in your codebase.
Migration Strategies
Identify and Mark Deprecated Associations
The first step is to go one by one and add this option if you consider it deprecated. To help you with it, if you need, you can list all the associations in your Rails code by doing:
ApplicationRecord.descendants.each_with_object({}) do |model, hash|
hash[model.name] = model.reflect_on_all_associations.map(&:name)
end
# {
# "Blog" => [:author],
# "Author" => [:blogs]
# }
In development, classes are loaded lazily, so .descendants won’t return all your models. Set config.eager_load = true to make sure every model is loaded before running this.
Detect Deprecated Associations in Your App
Once you’ve marked associations as deprecated, Rails will automatically report their usage. Here are practical ways to detect where deprecated associations are still being used:
- Run your test suite (locally or in CI) and review the output for deprecation warnings. Deprecated associations will trigger warnings or errors (depending on your reporting mode) whenever they’re accessed.
- Monitor logs in development, staging, and production. If you enabled backtraces, you’ll see exactly where in your code the deprecated association was used.
- For advanced tracking, set
mode: :notifyin your config and subscribe to thedeprecated_association.active_recordnotification. This lets you collect usage data or send alerts programmatically. - Finally, a manual search is always helpful, so check in your codebase for direct calls to deprecated associations (e.g.,
author.blogs,blog.author) using tools likegrepor your editor’s search feature. This helps you find places that may not be covered by tests.
These steps will help you find and remove any places in your app that still use deprecated associations.
Remove Associations and Columns
When you’re sure an association is not used anymore, you can safely remove it from your codebase by doing:
- Remove the association from your Rails models. If you’re not 100% sure, deploy this change first and keep an eye out for errors before moving on.
- If there’s a foreign key constraint, write a migration to remove it. This keeps your schema tidy and avoids orphaned records.
- Once you’re sure everything is safe, create a migration to drop the column. Always back up your data before dropping columns, especially in production.
This approach helps you avoid losing data by accident and keeps your app working well.
The Problem with Continuing to Use Deprecated Associations
If you keep deprecated associations in your app, you can have problems like:
- Your code becomes harder to maintain and upgrade, which can cause more bugs and confusion for your team.
- Old associations might not match your current data model, so you can get records without a parent. A few of these might not be a problem, but over time, orphaned data can become a real headache.
- Deprecated associations can give you wrong data in your analytics, reports, or when you connect your app to other systems.
In Conclusion
Deprecated associations are a useful feature in Rails 8.1 that make it easier to identify and safely remove outdated relationships from your application. They let you flag old relationships, find where they’re still being used, and clean them up safely before you remove the code and columns for good. If you keep an eye on the warnings and go step by step, you can remove old associations without breaking anything.
Give it a try in your own app next time you find an association nobody uses anymore, and see how it goes.
Looking to upgrade your Rails app or need a hand maintaining your Ruby projects? Contact us.