diff --git a/CHANGELOG.md b/CHANGELOG.md index b3f79dde7..c89c462ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Adding watchOS support, CocoaPods only (Cœur, #1363) * Updating CocoaLumberjack for 3.x support (LaurentiuUngur, #1352) * Fix date format parsing when local isn't US (Cœur, #964) +* Importing 'NSNull' for relationship sets its value to 'nil' instead of ignoring it. (burczyk, #1194) * Fix honouring multiple sort flags (deanWombourne, #1251) * CGFloat precision for `MR_colorFromString()` (Cœur, #1324) * To allow custom options like Data Protection level on the Core Data store files, we expose `MR_coordinatorWithSqliteStoreNamed:withOptions:` and `MR_coordinatorWithAutoMigratingSqliteStoreNamed:withOptions:` (leslie-lei, #1185) diff --git a/MagicalRecord.xcodeproj/project.pbxproj b/MagicalRecord.xcodeproj/project.pbxproj index 498d26b53..20725006e 100644 --- a/MagicalRecord.xcodeproj/project.pbxproj +++ b/MagicalRecord.xcodeproj/project.pbxproj @@ -829,6 +829,9 @@ 37CA2607229FEB7000EAB9F6 /* MagicalRecord.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MagicalRecord.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 37CA260F229FEB7000EAB9F6 /* MagicalRecord for tvOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MagicalRecord for tvOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 37CA2616229FEB7000EAB9F6 /* MagicalRecordTests-tvOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MagicalRecordTests-tvOS-Info.plist"; sourceTree = ""; }; + 37CF3EAD22BDFEFE00705F72 /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = SOURCE_ROOT; }; + 37CF3EAE22BDFEFE00705F72 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = SOURCE_ROOT; }; + 37CF3EAF22BDFEFE00705F72 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 581ECBEB187F63FF00084FEE /* ImportMultipleEntitiesWithNoPrimaryKeyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImportMultipleEntitiesWithNoPrimaryKeyTests.m; sourceTree = ""; }; 581ECBF6187F660B00084FEE /* MultipleEntitiesWithNoPrimaryKey.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = MultipleEntitiesWithNoPrimaryKey.json; path = Fixtures/MultipleEntitiesWithNoPrimaryKey.json; sourceTree = ""; }; 9004F5211A94CBCF00A61312 /* MagicalRecord for iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MagicalRecord for iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1096,6 +1099,9 @@ isa = PBXGroup; children = ( 90A0DE051C50D59300CF5A5A /* MagicalRecord.podspec */, + 37CF3EAE22BDFEFE00705F72 /* CHANGELOG.md */, + 37CF3EAD22BDFEFE00705F72 /* CONTRIBUTING.md */, + 37CF3EAF22BDFEFE00705F72 /* README.md */, 905D07C91A63DFED0076B54E /* Info.plist */, ); path = Support; diff --git a/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalDataImport.m b/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalDataImport.m index f1f9047be..fc0e89421 100644 --- a/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalDataImport.m +++ b/MagicalRecord/Categories/NSManagedObject/NSManagedObject+MagicalDataImport.m @@ -190,7 +190,7 @@ - (void)MR_setRelationships:(NSDictionary *)relationships forKeysWithObject:(id) } @finally { - if (relatedObjectData == nil || [relatedObjectData isEqual:[NSNull null]]) + if (relatedObjectData == nil) { continue; } @@ -210,6 +210,12 @@ - (void)MR_setRelationships:(NSDictionary *)relationships forKeysWithObject:(id) continue; } + if ([relatedObjectData isEqual:[NSNull null]]) + { + [self setValue:nil forKey:relationshipName]; + continue; + } + if ([relationshipInfo isToMany] && [relatedObjectData isKindOfClass:[NSArray class]]) { for (id singleRelatedObjectData in relatedObjectData) diff --git a/README.md b/README.md index 92ec8501d..99866bd6d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ In software engineering, the active record pattern is a design pattern found in > Active record is an approach to accessing data in a database. A database table or view is wrapped into a class; thus an object instance is tied to a single row in the table. After creation of an object, a new row is added to the table upon save. Any object loaded gets its information from the database; when an object is updated, the corresponding row in the table is also updated. The wrapper class implements accessor methods or properties for each column in the table or view. -> *- [Wikipedia]("https://en.wikipedia.org/wiki/Active_record_pattern")* +> *- [Wikipedia](https://en.wikipedia.org/wiki/Active_record_pattern)* MagicalRecord was inspired by the ease of Ruby on Rails' Active Record fetching. The goals of this code are: diff --git a/Tests/DataImport/ImportSingleEntityRelatedToManyMappedEntitiesUsingMappedPrimaryKeyTests.m b/Tests/DataImport/ImportSingleEntityRelatedToManyMappedEntitiesUsingMappedPrimaryKeyTests.m index 3f929c96f..199e45ebb 100644 --- a/Tests/DataImport/ImportSingleEntityRelatedToManyMappedEntitiesUsingMappedPrimaryKeyTests.m +++ b/Tests/DataImport/ImportSingleEntityRelatedToManyMappedEntitiesUsingMappedPrimaryKeyTests.m @@ -40,4 +40,23 @@ - (void)testImportData }]; } +- (void)testImportNilData +{ + SingleEntityRelatedToManyMappedEntitiesUsingMappedPrimaryKey *entity = [[self testEntityClass] MR_importFromObject:self.testEntityData inContext:[NSManagedObjectContext MR_defaultContext]]; + + XCTAssertNotNil(entity, @"Entity should not be nil"); + + [entity.managedObjectContext performBlockAndWait:^{ + // testing that importing nothing will not change the relationship + [entity MR_importValuesForKeysWithObject:@{}]; + NSUInteger mappedEntitiesCount = entity.mappedEntities.count; + XCTAssertEqual(mappedEntitiesCount, (NSUInteger)4, @"Expected 4 mapped entities, received %zd", mappedEntitiesCount); + + // testing that importing `null` will nullify the relationship + [entity MR_importValuesForKeysWithObject:@{@"mappedEntities":[NSNull null]}]; + mappedEntitiesCount = entity.mappedEntities.count; + XCTAssertEqual(mappedEntitiesCount, (NSUInteger)0, @"Expected 0 mapped entities, received %zd", mappedEntitiesCount); + }]; +} + @end