Repository navigation
Unwrap an Option assigned to a singular association writer - #65
Merged
Merged
Conversation
nz
force-pushed
the
nz/optional-readers-module
branch
from
September 8, 2026 21:51
b4ce1e8 to
e673919
Compare
nz
force-pushed
the
nz/association-writers-unwrap
branch
from
September 8, 2026 21:51
3231a85 to
520f5b7
Compare
An association writer looks like assignment to a typed field but is a setter, so it takes what the wrapped reader on another record hands back: Some(record) assigns the record, None() clears the association. Strictness stays on the reading side, where an absent value is the error to catch. Both macros reach SingularAssociation#writer, which neither BelongsToAssociation nor HasOneAssociation overrides, so one prepend covers them. Unwrapping there leaves the association's own type check in place, and a Some of the wrong class raises naming the class inside it.
The register is closed at five, and unwrapping on assignment is the same boundary coercion as the SQL-side unwrap rather than a sixth compromise, so item 3 names both boundaries.
Both reach the same writer, and both read the assigned record rather than only its key: a polymorphic belongs_to takes the foreign type from the record's class, and a has_one :through writes the join row from the record's own primary key. A polymorphic writer accepts any class, so it has no type check to reject a wrapper and instead fails reaching into it for a primary key.
nz
force-pushed
the
nz/association-writers-unwrap
branch
from
September 8, 2026 21:58
520f5b7 to
2976244
Compare
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #63. Stacked on #64.
Assigning an Option to a
belongs_toorhas_onewriter raisedAssociationTypeMismatch(andNone()too, since the writer tests truthiness rather thannil?), which broke the commonother.author = book.authoridiom whenever the source reader is wrapped. Strictness belongs on the reading side; on assignment it is ceremony. Singular association writers now coerce:Some(record)assigns as the record,None()as nil, one layer only. ASomeof the wrong class still raises the type mismatch, naming the inner class.One prepend on
ActiveRecord::Associations::SingularAssociation#writercoversbelongs_to, polymorphicbelongs_to,has_one, andhas_one :through: every generatedassoc=reacheswriter, and no subclass overrides it (the subclasses overridereplace, which is why a prepend there was not enough). Collection writers,build_/create_, nested attributes,where, and foreign-key_idwriters are untouched.The compromises register stays at five: item 3 now covers this boundary alongside quoting and predicate building.
Verified locally: rubocop (no new offenses), yard doctest, rake test,
nix build .#errgonomic,nix flake check --all-systems.