From 361fc986d01e5a1a65aca0514ed65da3d4857db7 Mon Sep 17 00:00:00 2001 From: SantiBecerra Date: Fri, 6 Nov 2020 11:18:34 +0100 Subject: [PATCH] Refactor of `func managedObjectsFrom(_ apiObjects: [APIObject], context: NSManagedObjectContext) throws -> [NSManagedObject]` to handle different entities in the APIObjects array Set version to 1.1.2 in podspec file --- Parsec.podspec | 4 ++-- Source/Parsec.swift | 48 +++++++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/Parsec.podspec b/Parsec.podspec index d00d473..b6fc570 100755 --- a/Parsec.podspec +++ b/Parsec.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Parsec" -s.version = "1.1.1" +s.version = "1.1.2" s.summary = "Modular JSON API to Core Data parser and validator" s.description = <<-DESC **Parsec** eases the task of getting `JSON API` documents into Core Data. @@ -8,7 +8,7 @@ DESC s.homepage = 'https://github.com/InQBarna/Parsec' s.license = 'MIT' s.author = { 'David Romacho' => 'david.romacho@inqbarna.com', 'Santiago Becerra' => 'santiago.becerra@inqbarna.com' } -s.source = { :git => "https://github.com/InQBarna/Parsec/Parsec.git", :tag => 'v1.1.1' } +s.source = { :git => "https://github.com/InQBarna/Parsec/Parsec.git", :tag => 'v1.1.2' } s.ios.deployment_target = '10.0' s.requires_arc = true diff --git a/Source/Parsec.swift b/Source/Parsec.swift index ed970dd..36329f5 100644 --- a/Source/Parsec.swift +++ b/Source/Parsec.swift @@ -396,33 +396,47 @@ public class Parsec { /// - returns: A `[NSManagedObject]`, empty if APIObjects is empty, order by apiObjects array id order. public func managedObjectsFrom(_ apiObjects: [APIObject], context: NSManagedObjectContext) throws -> [NSManagedObject] { - let apiObjectsIDs: [AnyHashable] = try apiObjects.map { + //Dictionary grouping objects by APIObject.type aka APIEntityName + let groupedAPIObjectsDict = Dictionary(grouping: apiObjects) { $0.type } + + //Needed to keeps the order in the returned array + let orderedAPIObjectsRemoteIDs: [AnyHashable] = try apiObjects.map { guard let remoteId = $0.id else { throw NSError(domain: "Parsec.Parsec", code: 2, userInfo: [NSLocalizedDescriptionKey: "APIObject (type '\($0.type)') without valid 'id'"]) } return remoteId } - guard let apiObject = apiObjects.first else { - return [NSManagedObject]() - } + var resultManagedObjects = [NSManagedObject]() - guard let serializer = entitiesByType[apiObject.type] else { - let message = String(format: "No serializer found for type '%@'", apiObject.type) - throw EntitySerializerErrorCode.unknownType.error(message) - } + try groupedAPIObjectsDict.forEach { (apiEntityName, apiObjectsByType) in + let apiObjectsRemoteIDsByType: [AnyHashable] = try apiObjectsByType.map { + guard let remoteId = $0.id else { + throw NSError(domain: "Parsec.Parsec", code: 2, userInfo: [NSLocalizedDescriptionKey: "APIObject (type '\($0.type)') without valid 'id'"]) + } + return remoteId + } - let fr: NSFetchRequest = NSFetchRequest(entityName: serializer.name) - fr.predicate = NSPredicate(format: "id IN %@", apiObjectsIDs) + guard let serializer = entitiesByType[apiEntityName] else { + let message = String(format: "No serializer found for type '%@'", apiEntityName) + throw EntitySerializerErrorCode.unknownType.error(message) + } + + let fr: NSFetchRequest = NSFetchRequest(entityName: serializer.name) + fr.predicate = NSPredicate(format: "id IN %@", apiObjectsRemoteIDsByType) - let managedObjects = try context.fetch(fr) - try context.obtainPermanentIDs(for: managedObjects) + let managedObjectsByType = try context.fetch(fr) + + guard apiObjectsRemoteIDsByType.count == managedObjectsByType.count else { + throw NSError(domain: "Parsec.Parsec", code: 3, userInfo: [NSLocalizedDescriptionKey: "APIObjects array and ManagedObjects retrieved must contains the same number of items"]) + } - guard apiObjectsIDs.count == managedObjects.count else { - throw NSError(domain: "Parsec.Parsec", code: 3, userInfo: [NSLocalizedDescriptionKey: "APIObjects array and ManagedObjects retrieved must contains the same number of items"]) + resultManagedObjects.append(contentsOf: managedObjectsByType) } - let result = try managedObjects.sorted { (leftObject, rightObject) -> Bool in + try context.obtainPermanentIDs(for: resultManagedObjects) + + let result = try resultManagedObjects.sorted { (leftObject, rightObject) -> Bool in guard let leftID = leftObject.value(forKey: "id") as? AnyHashable, let rightID = rightObject.value(forKey: "id") as? AnyHashable @@ -431,8 +445,8 @@ public class Parsec { } guard - let leftIndex = apiObjectsIDs.firstIndex(of: leftID), - let rightIndex = apiObjectsIDs.firstIndex(of: rightID) + let leftIndex = orderedAPIObjectsRemoteIDs.firstIndex(of: leftID), + let rightIndex = orderedAPIObjectsRemoteIDs.firstIndex(of: rightID) else { throw NSError(domain: "Parsec.Parsec", code: 5, userInfo: [NSLocalizedDescriptionKey: "Index for ManagedObject 'id' not found in APIObject param array"]) }