Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to merge policy #80

Merged
merged 5 commits into from
Jun 26, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Updates to merge policy
  • Loading branch information
Conrad Stoll committed Jun 25, 2014
commit 5af13e010317f2cdc1073f4b517cbdcd438f5c57
12 changes: 8 additions & 4 deletions Source/MMRecord/MMRecordMarshaler.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@
relationships on various other records. Generally speaking, its expected that a response will
contain either duplicate references to record primary keys, which allow MMRecord to fetch the
appropriate record to associate as a relationship. Or, the response may contain duplicate fully
saturated objects. In this case, the first object will "win", and all other references to that
object will be populated using the first one that is found.
saturated objects. In this case, the first fully saturated object will "win", and all other
references to that object will be populated using the first one that is found.

This method is intended as a means to merge those various different response objects together to
create a master instance of a particular record. In some responses an object may contain a subset
Expand All @@ -128,8 +128,12 @@
@param dictionary The dictionary for the n+1th record response object of a given type and
primary key.
@param protoRecord The proto record created to represent this specific object by MMRecord.
@discussion This method has no default implementation. You must subclass MMRecordMarshaler to
provide your own implementation.
@discussion The default implementation of this method will look for cases where a given record is
only identified by a primary key and includes no additional data to populate it with. In this case
the primary key of that original proto record will be compared with the incoming object dictionary
and if they match then the new dictionary will be associated with the proto record.
@warning If you decide to subclass this method you may want to use the super implementation
as a starting point for your own implementation. Calling super is not required, but is recommended.
*/
+ (void)mergeDuplicateRecordResponseObjectDictionary:(NSDictionary *)dictionary
withExistingProtoRecord:(MMRecordProtoRecord *)protoRecord;
Expand Down
26 changes: 25 additions & 1 deletion Source/MMRecord/MMRecordMarshaler.m
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,31 @@ + (void)establishPrimaryKeyRelationshipFromProtoRecord:(MMRecordProtoRecord *)pr

+ (void)mergeDuplicateRecordResponseObjectDictionary:(NSDictionary *)dictionary
withExistingProtoRecord:(MMRecordProtoRecord *)protoRecord {
// There is no default implementation for this method. Feel free to provide your own :)
if ([protoRecord.dictionary.allKeys count] == 1) {
NSAttributeDescription *primaryAttributeDescription = protoRecord.representation.primaryAttributeDescription;
NSArray *primaryKeyPaths = [protoRecord.representation keyPathsForMappingAttributeDescription:primaryAttributeDescription];

BOOL dictionariesContainIdenticalPrimaryKeys = NO;

for (NSString *keyPath in primaryKeyPaths) {
id dictionaryValue = [dictionary valueForKeyPath:keyPath];
id protoRecordValue = [dictionary valueForKeyPath:keyPath];

if ([dictionaryValue isKindOfClass:[NSNumber class]] && [protoRecordValue isKindOfClass:[NSNumber class]]) {
dictionariesContainIdenticalPrimaryKeys = [dictionaryValue isEqualToNumber:protoRecordValue];
} else if ([dictionaryValue isKindOfClass:[NSString class]] && [protoRecordValue isKindOfClass:[NSString class]]) {
dictionariesContainIdenticalPrimaryKeys = [dictionaryValue isEqualToString:protoRecordValue];
}

if (dictionariesContainIdenticalPrimaryKeys) {
break;
}
}

if (dictionariesContainIdenticalPrimaryKeys) {
protoRecord.dictionary = dictionary;
}
}
}


Expand Down
22 changes: 13 additions & 9 deletions Source/MMRecord/MMRecordResponse.m
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ - (MMRecordProtoRecord *)protoRecordWithRecordResponseObject:(id)recordResponseO
entity:entity
representation:representation];


if (proto.hasRelationshipPrimarykey == NO) {
if (proto.primaryKeyValue == nil) {
if (self.options.entityPrimaryKeyInjectionBlock != nil) {
Expand Down Expand Up @@ -303,16 +304,19 @@ - (void)addRelationshipProtoRecordsToProtoRecord:(MMRecordProtoRecord *)protoRec
}

for (id object in relationshipObject) {
NSEntityDescription *recordSubEntity = [self subEntityForRecordResponseObject:object
withInitialEntity:entity];

MMRecordProtoRecord *relationshipProto = [self protoRecordWithRecordResponseObject:object
entity:recordSubEntity
existingResponseGroups:responseGroups
parentProtoRecord:protoRecord];

// By keeping the above section of code outside the conditional we can gaurantee that
// the protoRecord generation/parsing method above gets called for every relationship
// proto, which also causes the optional merge code to be run for all possible updated
// relationship protos.
if ([protoRecord canAccomodateAdditionalProtoRecordForRelationshipDescription:relationshipDescription]) {

NSEntityDescription *recordSubEntity = [self subEntityForRecordResponseObject:object
withInitialEntity:entity];

MMRecordProtoRecord *relationshipProto = [self protoRecordWithRecordResponseObject:object
entity:recordSubEntity
existingResponseGroups:responseGroups
parentProtoRecord:protoRecord];

[protoRecord addRelationshipProto:relationshipProto
forRelationshipDescription:relationshipDescription];
}
Expand Down