Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions Parsec.podspec
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
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.
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
Expand Down
48 changes: 31 additions & 17 deletions Source/Parsec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<NSManagedObject> = 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<NSManagedObject> = 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
Expand All @@ -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"])
}
Expand Down