Dependency injection when creating custom model document ID in CBL 1.1.1+

36 views
Skip to first unread message

Scott Ahten

unread,
Feb 2, 2016, 2:34:13 PM2/2/16
to Couchbase Mobile
While migrating an existing CBL iOS client to CBL 1.1.1, I've run into an issue where I need to inject a dependency for the logic that creates a custom document ID with multiple components, such as "type:GUID:subtype"

In 1.1.1, we have - [CBLModel modelForDocument:], [CBLModel awakeFromInitializer] and -[CBLModel idForNewDocumentInDatabase]. While the particular subclass can be used to derive the type component in my scenerio, the logic in idForNewDocumentInDatabase needs to know what subtype is being requested to derive the last fragment of document ID. This was previously passed into the initializer. 

A contrived example would be [[MySubclass alloc] initWithNewMyModelInDatabase:aDatabase subtype:@"thumbnail"]; At which point, idForNewDocumentInDatabase could reference self.subtype to generate the custom document ID. 

Is there a way to inject the subtype dependency to idForNewDocumentInDatabase in 1.1.1?

Jens Alfke

unread,
Feb 2, 2016, 3:27:40 PM2/2/16
to mobile-c...@googlegroups.com
In your situation I suggest not using +modelForNewDocumentInDatabase: at all. Instead create the docID first, then get a (new) document for it, then get the model for that document:

NSString* newDocID = …whatever you want, incorporating some sort of UUID…;
CBLDocument* doc = [_db documentWithID: newDocID];
MySubclass *model = [MySubclass modelForDocument: doc];

—Jens

Scott Ahten

unread,
Feb 2, 2016, 4:51:42 PM2/2/16
to Couchbase Mobile
Thanks for your quick reply. I was about to head down this road and your response told me I was headed in the right direction. 

Ended up making a class method to encapsulate creating the composite document ID. My creation class method looks similar to....

+ (instancetype)newMyModelWithSubtype:(NSString*)subtype
                                           inDatabase
:(CBLDatabase*)database
{
   
NSString *modelID = [MyModelClass documentIDForSubtype:subtype];
   
CBLDocument *modelDocument = [database documentWithID:modelID];
   
MyModelClass *newModel = [MyModelClass modelForDocument:modelDocument];
   
return newModel
}


- (void)awakeFromInitializer
{
   
[self setValue:@"my-model" ofProperty:@"type"];
}

Jens Alfke

unread,
Feb 2, 2016, 7:00:56 PM2/2/16
to mobile-c...@googlegroups.com

On Feb 2, 2016, at 1:51 PM, Scott Ahten <lightand...@gmail.com> wrote:

- (void)awakeFromInitializer
{
   
[self setValue:@"my-model" ofProperty:@"type"];
}


I don’t recommend setting any properties (especially ‘type’) in -awakeFromInitializer. Instead, set the ‘type’ property when creating the document, i.e. in the +newMyModel… method. This helps consolidate your document initialization code and ensures that the document can’t be declared (via its ‘type’) as being a MyModel without having the other required properties set.

(We found a bug in ToDoLite last week that was like this. It was possible to load a Task model object for a nonexistent document, which led to the ‘type’ property being set by a method like the one above, and then autosave caused the bogus Task to be saved to the database. Unfortunately the document had no other properties, so a view’s map function that tried to operate on its listID barfed when it got nil.)

—Jens
Reply all
Reply to author
Forward
0 new messages