Skip to content

Conversation

@seanpdoyle
Copy link
Contributor

@seanpdoyle seanpdoyle commented Nov 9, 2025

The Base class defines an attr_accessor :attributes that is marked
with # :nodoc:. Technically, this means that any interaction with
Base#attributes or Base#attributes= is not part of the public
interface, and is free to be changed or removed without breaking the
public API.

However, given the project's age and the long-term period of time with
minimal changes to the public interface, this PR proposes that there be
a public deprecation of writing to the Hash instance returned by the
Base#attributes method.

The migration to ActiveModel::Attributes proposed in #410 will
involve changes to the Base#attributes method (due to
ActiveModel::Attributes#attributes). Reading from the value returned
by ActiveModel::Attributes#attributes will remain the same, but
writing to that value will have no affect since the value is a Hash copy
created by ActiveModel::AttributeSet#to_hash, and not the Hash
instance used internally.

Similarly, ActiveModel::Attributes does not expose a corresponding
#attributes= method. By deprecating #attributes=, changes made that
incorporate ActiveModel::Attributes will not need to add an otherwise
unnecessary #attributes= implementation.

Once deprecated and part of a release cycle, the
ActiveResource::AttributeSet class can be removed, and the Active
Model migration's backwards compatibility burden can be reduced.

end

attr_accessor :attributes # :nodoc:
attr_writer :attributes # :nodoc:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These attributes are marked with # :nodoc:, so they're private and free from the typical rules applied to breaking changes.

Is a deprecation cycle too cautious?

Could this PR be closed without the changes to #attributes proposed in #410 being considered breaking changes?

The Base class defines an `attr_accessor :attributes` that is marked
with `# :nodoc:`. Technically, this means that any interaction with
`Base#attributes` or `Base#attributes=` is not part of the public
interface, and is free to be changed or removed without breaking the
public API.

However, given the project's age and the long-term period of time with
minimal changes to the public interface, this PR proposes that there be
a public deprecation of **writing** to the Hash instance returned by the
`Base#attributes` method.

The migration to `ActiveModel::Attributes` proposed in [rails#410][] will
involve changes to the `Base#attributes` method (due to
[ActiveModel::Attributes#attributes][]). Reading from the value returned
by `ActiveModel::Attributes#attributes` will remain the same, but
writing to that value will have no affect since the value is a Hash copy
created by [ActiveModel::AttributeSet#to_hash][], and not the Hash
instance used internally.

Similarly, `ActiveModel::Attributes` does not expose a corresponding
`#attributes=` method. By deprecating `#attributes=`, changes made that
incorporate `ActiveModel::Attributes` will not need to add an otherwise
unnecessary `#attributes=` implementation.

Once deprecated and part of a release cycle, the
`ActiveResource::AttributeSet` class can be removed, and the Active
Model migration's backwards compatibility burden can be reduced.

[rails#410]: rails#410
[ActiveModel::Attributes#attributes]: https://edgeapi.rubyonrails.org/classes/ActiveModel/Attributes.html#method-i-attributes
[ActiveModel::AttributeSet#to_hash]: https://github.com/rails/rails/blob/v8.1.1/activemodel/lib/active_model/attribute_set.rb#L36-L39
@seanpdoyle seanpdoyle force-pushed the deprecate-attributes-write branch from b2bc3ad to 15cb07e Compare November 9, 2025 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant