You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
belongs_to detach: null the FK if nullable, error if not (#3127)
* belongs_to detach: null the FK if nullable, clean error if not
`delete_<field>()` on a belongs_to (`ActiveHasOne::Delete`) was silently ignored on
save β `take()` mapped `Delete` to `None`, so the branch did nothing and the foreign
key was never touched.
Handle it in the belongs_to save action: `clear_parent_key::<Related>()` nulls this
row's FK when the column is nullable, and returns `false` when it is not β in which
case we return a clean `DbErr::Type` ("relation cannot be detached") instead of
attempting an UPDATE that a raw NOT NULL constraint would reject. Composite FKs are
handled by the relation def. Also make `clear_key_on_active_model` a no-op when the
FK column was never set (a freshly-built ActiveModel) rather than erroring, so
`delete_<field>()` on a fresh model just inserts NULL.
Keeps the single `ActiveHasOne` type β nullability drives behavior at runtime rather
than being encoded in the type.
Adds tests for nullable detach, non-nullable clean error, and detach-on-unset no-op.
* Use if-let over single-arm match in clear_key_on_active_model (clippy)
* Support nested writes for duplicate-target belongs_to
When two belongs_to fields share a target entity (e.g. `user_follower.user` +
`user_follower.follower`, both -> `user`), there is no unique `Related<E>` to key
the FK write by, so the save action's `entity_count == 1` guard dropped them
entirely β nested writes silently no-op'd.
Route such relations through the relation-keyed helpers instead: capture their
relation variant at detection time (the explicit `relation_enum`, else the default
inferred the same way the loader/model_ex does) and use `set_parent_key_for` /
`clear_parent_key_for(Relation::X)`. Unique-target belongs_to keep the entity-keyed
path unchanged. Adds `ActiveModelTrait::clear_parent_key_for` (the relation-keyed
counterpart to `clear_parent_key`, mirroring `set_parent_key_for`).
Adds `test_belongs_to_duplicate_target`.
0 commit comments