Skip to content

Introduce support for deprecated associations API #1681

@matsales28

Description

@matsales28

Feature Request: Add support for deprecated association attribute

Background

Rails 8.1 introduced the ability to mark Active Record
associations as deprecated. This allows
developers to mark associations for deprecation while maintaining
backward compatibility.

Current Rails Behavior

Associations can now be marked as deprecated:

class Author < ApplicationRecord
  has_many :posts, deprecated: true
  has_one :profile, deprecated: true
  belongs_to :publisher, deprecated: true
end

When a deprecated association is used, Rails will report the
usage according to the configured reporting mode. The reporting
behavior (mode and backtrace options) is configured globally or
per-model, not on the association declaration itself.

Reporting modes (configured separately):

  • :warn - Issues a deprecation warning (default)
  • :raise - Raises an exception
  • :notify - Sends a notification via ActiveSupport::Notifications

Proposed Feature

Add matcher support to test that associations are properly marked
as deprecated:

Assert association is deprecated

it { should have_many(:posts).deprecated }
it { should have_one(:profile).deprecated }
it { should belong_to(:author).deprecated }

Assert association is NOT deprecated

it { should have_many(:posts).deprecated(false) }

or

it { should_not have_many(:posts).deprecated }

Implementation Considerations

  1. The feature should work with all association types:
    - has_many
    - has_one
    - belongs_to
    - has_and_belongs_to_many
    - has_many :through
  2. The matcher should only verify the deprecated: true attribute:
    - Should check if the association has deprecated: true set
    - Should NOT test reporting mode or backtrace settings (those
    are configuration concerns)
  3. Rails version compatibility:
    - This feature requires Rails 8.1+
    - Should gracefully skip or provide helpful error on older
    Rails versions

Example Test Cases

  RSpec.describe 'deprecated association matcher' do
    context 'with deprecated association' do
      it 'matches when association is deprecated' do
        define_model :Author do
          has_many :posts, deprecated: true
        end

        expect(Author.new).to have_many(:posts).deprecated
      end

      it 'works with different association types' do
        define_model :Author do
          has_one :profile, deprecated: true
          belongs_to :publisher, deprecated: true
        end

        expect(Author.new).to have_one(:profile).deprecated
        expect(Author.new).to belong_to(:publisher).deprecated
      end
    end

    context 'without deprecated association' do
      it 'does not match when association is not deprecated' do
        define_model :Author do
          has_many :posts
        end

        expect(Author.new).not_to have_many(:posts).deprecated
      end

      it 'can explicitly assert not deprecated' do
        define_model :Author do
          has_many :posts
        end

        expect(Author.new).to have_many(:posts).deprecated(false)
      end
    end
  end

Usage Example

  # In your model
  class Author < ApplicationRecord
    has_many :legacy_posts, deprecated: true
    has_many :posts
  end

  # In your spec
  RSpec.describe Author do
    it { should have_many(:legacy_posts).deprecated }
    it { should have_many(:posts).deprecated(false) }
    # or
    it { should_not have_many(:posts).deprecated }
  end

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions