Best way to handle dependent documents (one-to-x relationship) on deletion?

98 views
Skip to first unread message

Pascal

unread,
Dec 22, 2013, 3:41:04 PM12/22/13
to mobile-c...@googlegroups.com
I'm not sure how to handle deletes properly in this scenario:

I have a "Person" model that may have a "Note" model as a property. Works fine, in Person's `save:` I check for the note property as well and save it when needed. I did the same in `deleteDocument:` of Person, also delete the note if one exists. However, when deleting Person objects from a table view with Couchbase Lite's nice table view source, `deleteDocument:` doesn't get called and the person's note lives on a lonely live in the database.

What's the best way to handle such dependencies, should I use a validator and delete the note in that block when the person gets a tombstone? Since I intend to have another property on Person objects that will be an array of models this question also extends to the case of one-to-many relationships.

Pascal

unread,
Dec 22, 2013, 7:58:22 PM12/22/13
to mobile-c...@googlegroups.com
(I am now using couchTableSource:deleteRow: and call deleteDocument: from in there but am wondering about best practices.)

Pascal

unread,
Jan 2, 2014, 12:26:35 PM1/2/14
to mobile-c...@googlegroups.com
To answer my own question, maybe this is useful to somebody else: it seems handling deletion of dependent documents (for example a one-to-many relationship between people and note documents belonging to somebody) is best done in a validation block. I have implemented a method "didDelete" on my Person class and here is the block that ensures that a person's note documents get deleted if their owning person gets deleted:

[_database setValidationNamed:@"personNoteValidation"

                      asBlock:^(CBLRevision *newRevision, id<CBLValidationContext> context) {

 

                              // delete notes on person deletion

                              if (newRevision.isDeletion && [@"person" isEqualToString:newRevision.document.properties[@"type"]]) {

                                  PersonClass *person = [PersonClass modelForDocument:newRevision.document];

                                  [person didDelete];

                              }

                       }];


For some reason, newRevision.properties was always null, hence I'm using newRevision.document.

Jens Alfke

unread,
Jan 2, 2014, 2:49:04 PM1/2/14
to mobile-c...@googlegroups.com

On Jan 2, 2014, at 9:26 AM, Pascal <phase.o...@gmail.com> wrote:

To answer my own question, maybe this is useful to somebody else: it seems handling deletion of dependent documents (for example a one-to-many relationship between people and note documents belonging to somebody) is best done in a validation block.

I’m a nervous about the idea of a validation block making changes to the database, for instance if your -didDelete method ends up deleting other documents. It will trigger a re-entrant call to the document-updating code, and I’m not sure that will behave correctly in all cases.

It would be safest if you delayed the call to -didDelete, e.g. by putting it in a dispatch_async block.

For some reason, newRevision.properties was always null, hence I'm using newRevision.document.

Deleting a document creates a revision with no properties (except a magic “_deleted”:true tombstone.) If you want to look at the properties of the existing revision, look at oldRevision.properties.

—Jens

Pascal

unread,
Jan 3, 2014, 7:24:05 AM1/3/14
to mobile-c...@googlegroups.com

On Thursday, January 2, 2014 8:49:04 PM UTC+1, Jens Alfke wrote:

I’m a nervous about the idea of a validation block making changes to the database, for instance if your -didDelete method ends up deleting other documents. It will trigger a re-entrant call to the document-updating code, and I’m not sure that will behave correctly in all cases.

It would be safest if you delayed the call to -didDelete, e.g. by putting it in a dispatch_async block.

It does re-enter the validation before the first block finishes, in my tests (and when stepping through) it worked nicely but yes, I'll put it in a dispatch block just to be safe.


For some reason, newRevision.properties was always null, hence I'm using newRevision.document.

Deleting a document creates a revision with no properties (except a magic “_deleted”:true tombstone.) If you want to look at the properties of the existing revision, look at oldRevision.properties.

That's what I also tried but the parentRevision and parentRevisionID properties were null as well.

Jens Alfke

unread,
Jan 3, 2014, 12:56:00 PM1/3/14
to mobile-c...@googlegroups.com

On Jan 3, 2014, at 4:24 AM, Pascal <phase.o...@gmail.com> wrote:

>> Deleting a document creates a revision with no properties (except a magic “_deleted”:true tombstone.) If you want to look at the properties of the existing revision, look at oldRevision.properties.
>
> That's what I also tried but the parentRevision and parentRevisionID properties were null as well.

Sorry, I meant `context.currentRevision.properties`.

Sounds like a bug that `newRevision.parentRevision` is nil … I’ll take a look.

—Jens
Reply all
Reply to author
Forward
0 new messages