Reference-owned one-to-one multiplicity
- Status: Decided
- Date: 2026-07-24
Context
The pre-refoundation relationship model distinguished one-to-one from one-to-many edges on Reference. During the
documentation reorganization, the machine-readable format lost that fact while retaining a cardinality object
on Association.
Those values answer different questions. Reference multiplicity asks whether two referencing records may point to the same target. Association cardinality bounds one named traversal, possibly after applying a Predicate. The latter cannot safely imply foreign-key uniqueness because the referenced-side Association may be omitted or filtered.
Dunbar150 exposed both meanings:
- only one Profile may reference a User;
- only one FeedCursor may reference a Profile;
- every Profile should have a FeedCursor; and
- only one ordinary FeedEntry may reference a Post, while catch-up entries may repeat that Post.
The first two are stored-edge structure. The third is a referenced-side existence rule. The fourth is conditional uniqueness rather than a one-to-one edge.
Direction
A Reference may carry:
"one_to_one": true
The optional boolean defaults to false. True means that at most one referencing record may point to each logical target. It does not mean every target must be referenced.
The Rails profile derives Reference-bound uniqueness feedback and unique target storage from this meaning. A
referenced-side direct Association derives has_one; otherwise it derives has_many. A direct Association does
not repeat maximum: 1 merely to select its macro.
Association cardinality remains available for additional bounds on a named traversal. A minimum can require a referenced-side record to exist. A Predicate-qualified maximum can constrain a subset while the underlying Reference remains many-to-one.
Global single-Reference uniqueness that only expresses one-to-one structure moves to one_to_one. Field
uniqueness, compound tuples, and conditional uniqueness remain Entity Validations with an explicit
error_target.
Alternatives considered
Infer one-to-one from Association cardinality
Rejected because a Reference remains meaningful without a referenced-side Association. A filtered Association maximum also does not make the underlying foreign key unique.
Infer one-to-one from a uniqueness Validation
Rejected as the primary representation because the Compiler would need to discover relationship shape inside a general rule registry. It would also make a structural edge indistinguishable from conditional uniqueness such as one ordinary FeedEntry per Post.
Restore the old cardinality enum
Not selected. one_to_many was easy to read from the opposite orientation, and reusing cardinality beside the
Association's minimum-and-maximum object would preserve the earlier ambiguity. The positive boolean records the
only non-default structural case currently needed.
Consequences and open proof
- A single-target Rails lowering needs model feedback bound to the Reference and a unique index on its foreign-key column.
- A polymorphic lowering would need uniqueness over its type-and-ID pair.
- An exclusive arc would need uniqueness for each possible non-null target column.
- Optional one-to-one References still permit multiple nulls.
- The semantic validator must reject a direct Association maximum that merely repeats Reference multiplicity while preserving genuinely qualified Association bounds.
- The References topic owns current Rails lowering and proof for this shape.