From b6ee0b014f60430cb9e60b4f159fc5429372d4ac Mon Sep 17 00:00:00 2001 From: John Rommel Estropia Date: Tue, 24 Oct 2017 00:31:27 +0900 Subject: [PATCH] WIP: documentations --- Sources/BaseDataTransaction+Querying.swift | 106 ++++++++++++++++-- Sources/BaseDataTransaction.swift | 24 ++-- Sources/ChainedClauseBuilder.swift | 5 + Sources/CoreStore+Querying.swift | 104 +++++++++++++++-- Sources/DataStack+Querying.swift | 104 +++++++++++++++-- Sources/FetchableSource.swift | 65 ++++++++++- Sources/ImportableAttributeType.swift | 6 + Sources/Into.swift | 16 +-- Sources/NSManagedObjectContext+Querying.swift | 3 - Sources/QueryableSource.swift | 39 ++++++- Sources/Relationship.swift | 9 ++ Sources/Transformable.swift | 10 +- Sources/Value.swift | 7 ++ 13 files changed, 444 insertions(+), 54 deletions(-) diff --git a/Sources/BaseDataTransaction+Querying.swift b/Sources/BaseDataTransaction+Querying.swift index 0ece0ae..7661762 100644 --- a/Sources/BaseDataTransaction+Querying.swift +++ b/Sources/BaseDataTransaction+Querying.swift @@ -68,7 +68,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { /** Deletes all `DynamicObject`s that satisfy the specified conditions. ``` - transaction.deleteAll(From().where(\.age > 50) + transaction.deleteAll(From().where(\.age > 50)) ``` - parameter clauseChain: a `FetchChainableBuilderType` clause chain created from a `From` clause - returns: the number of `DynamicObject`s deleted @@ -163,7 +163,18 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { return self.context.fetchOne(from, fetchClauses) } - // TODO: docs + /** + Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let youngestTeen = transaction.fetchOne( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` + */ public func fetchOne(_ clauseChain: B) -> B.ObjectType? { CoreStore.assert( @@ -205,7 +216,18 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { return self.context.fetchAll(from, fetchClauses) } - // TODO: docs + /** + Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let people = transaction.fetchAll( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` + */ public func fetchAll(_ clauseChain: B) -> [B.ObjectType]? { CoreStore.assert( @@ -247,7 +269,18 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { return self.context.fetchCount(from, fetchClauses) } - // TODO: docs + /** + Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let numberOfAdults = transaction.fetchCount( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` + */ public func fetchCount(_ clauseChain: B) -> Int? { CoreStore.assert( @@ -289,7 +322,18 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { return self.context.fetchObjectID(from, fetchClauses) } - // TODO: docs + /** + Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let youngestTeenID = transaction.fetchObjectID( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` + */ public func fetchObjectID(_ clauseChain: B) -> NSManagedObjectID? { CoreStore.assert( @@ -331,7 +375,18 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { return self.context.fetchObjectIDs(from, fetchClauses) } - // TODO: docs + /** + Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let idsOfAdults = transaction.fetchObjectIDs( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` + */ public func fetchObjectIDs(_ clauseChain: B) -> [NSManagedObjectID]? { CoreStore.assert( @@ -382,7 +437,20 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { return self.context.queryValue(from, selectClause, queryClauses) } - // TODO: docs + /** + Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses. + + A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. + ``` + let averageAdultAge = transaction.queryValue( + From() + .select(Int.self, .average(\.age)) + .where(\.age > 18) + ) + ``` + - parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request. + - returns: the result of the the query as specified by the `QueryChainableBuilderType` + */ public func queryValue(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType { CoreStore.assert( @@ -430,7 +498,29 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { return self.context.queryAttributes(from, selectClause, queryClauses) } - // TODO: docs + /** + Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses. + + A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. + ``` + let results = dataStack.queryAttributes( + From() + .select( + NSDictionary.self, + .attribute(\.age, as: "age"), + .count(\.age, as: "numberOfPeople") + ) + .groupBy(\.age) + ) + for dictionary in results! { + let age = dictionary["age"] as! Int + let count = dictionary["numberOfPeople"] as! Int + print("There are \(count) people who are \(age) years old." + } + ``` + - parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request. + - returns: the result of the the query as specified by the `QueryChainableBuilderType` + */ public func queryAttributes(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary { CoreStore.assert( diff --git a/Sources/BaseDataTransaction.swift b/Sources/BaseDataTransaction.swift index b9590a6..0c75700 100644 --- a/Sources/BaseDataTransaction.swift +++ b/Sources/BaseDataTransaction.swift @@ -116,10 +116,10 @@ public /*abstract*/ class BaseDataTransaction { } /** - Returns an editable proxy of a specified `NSManagedObject`. + Returns an editable proxy of a specified `NSManagedObject` or `CoreStoreObject`. - - parameter object: the `NSManagedObject` type to be edited - - returns: an editable proxy for the specified `NSManagedObject`. + - parameter object: the `NSManagedObject` or `CoreStoreObject` type to be edited + - returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`. */ public func edit(_ object: D?) -> D? { @@ -139,7 +139,7 @@ public /*abstract*/ class BaseDataTransaction { - parameter into: an `Into` clause specifying the entity type - parameter objectID: the `NSManagedObjectID` for the object to be edited - - returns: an editable proxy for the specified `NSManagedObject`. + - returns: an editable proxy for the specified `NSManagedObject` or `CoreStoreObject`. */ public func edit(_ into: Into, _ objectID: NSManagedObjectID) -> D? { @@ -156,9 +156,9 @@ public /*abstract*/ class BaseDataTransaction { } /** - Deletes a specified `NSManagedObject`. + Deletes a specified `NSManagedObject` or `CoreStoreObject`. - - parameter object: the `NSManagedObject` to be deleted + - parameter object: the `NSManagedObject` or `CoreStoreObject` to be deleted */ public func delete(_ object: D?) { @@ -173,11 +173,11 @@ public /*abstract*/ class BaseDataTransaction { } /** - Deletes the specified `NSManagedObject`s. + Deletes the specified `NSManagedObject`s or `CoreStoreObject`s. - - parameter object1: the `NSManagedObject` to be deleted - - parameter object2: another `NSManagedObject` to be deleted - - parameter objects: other `NSManagedObject`s to be deleted + - parameter object1: the `NSManagedObject` or `CoreStoreObject` to be deleted + - parameter object2: another `NSManagedObject` or `CoreStoreObject` to be deleted + - parameter objects: other `NSManagedObject`s or `CoreStoreObject`s to be deleted */ public func delete(_ object1: D?, _ object2: D?, _ objects: D?...) { @@ -185,9 +185,9 @@ public /*abstract*/ class BaseDataTransaction { } /** - Deletes the specified `NSManagedObject`s. + Deletes the specified `NSManagedObject`s or `CoreStoreObject`s. - - parameter objects: the `NSManagedObject`s to be deleted + - parameter objects: the `NSManagedObject`s or `CoreStoreObject`s to be deleted */ public func delete(_ objects: S) where S.Iterator.Element: DynamicObject { diff --git a/Sources/ChainedClauseBuilder.swift b/Sources/ChainedClauseBuilder.swift index 4403610..a20974d 100644 --- a/Sources/ChainedClauseBuilder.swift +++ b/Sources/ChainedClauseBuilder.swift @@ -27,6 +27,8 @@ import Foundation import CoreData +// MARK: - FetchChainableBuilderType + public protocol FetchChainableBuilderType { associatedtype ObjectType: DynamicObject @@ -35,6 +37,9 @@ public protocol FetchChainableBuilderType { var fetchClauses: [FetchClause] { get set } } + +// MARK: - QueryChainableBuilderType + public protocol QueryChainableBuilderType { associatedtype ObjectType: DynamicObject diff --git a/Sources/CoreStore+Querying.swift b/Sources/CoreStore+Querying.swift index 4a6e43f..4c4cad7 100644 --- a/Sources/CoreStore+Querying.swift +++ b/Sources/CoreStore+Querying.swift @@ -99,7 +99,18 @@ public extension CoreStore { return self.defaultStack.fetchOne(from, fetchClauses) } - // TODO: docs + /** + Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let youngestTeen = CoreStore.fetchOne( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` + */ public static func fetchOne(_ clauseChain: B) -> B.ObjectType? { return self.defaultStack.fetchOne(clauseChain) @@ -129,7 +140,18 @@ public extension CoreStore { return self.defaultStack.fetchAll(from, fetchClauses) } - // TODO: docs + /** + Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let people = CoreStore.fetchAll( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` + */ public static func fetchAll(_ clauseChain: B) -> [B.ObjectType]? { return self.defaultStack.fetchAll(clauseChain) @@ -159,7 +181,18 @@ public extension CoreStore { return self.defaultStack.fetchCount(from, fetchClauses) } - // TODO: docs + /** + Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let numberOfAdults = CoreStore.fetchCount( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` + */ public static func fetchCount(_ clauseChain: B) -> Int? { return self.defaultStack.fetchCount(clauseChain) @@ -189,7 +222,18 @@ public extension CoreStore { return self.defaultStack.fetchObjectID(from, fetchClauses) } - // TODO: docs + /** + Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let youngestTeenID = CoreStore.fetchObjectID( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` + */ public static func fetchObjectID(_ clauseChain: B) -> NSManagedObjectID? { return self.defaultStack.fetchObjectID(clauseChain) @@ -219,7 +263,18 @@ public extension CoreStore { return self.defaultStack.fetchObjectIDs(from, fetchClauses) } - // TODO: docs + /** + Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let idsOfAdults = transaction.fetchObjectIDs( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` + */ public static func fetchObjectIDs(_ clauseChain: B) -> [NSManagedObjectID]? { return self.defaultStack.fetchObjectIDs(clauseChain) @@ -255,7 +310,20 @@ public extension CoreStore { return self.defaultStack.queryValue(from, selectClause, queryClauses) } - // TODO: docs + /** + Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses. + + A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. + ``` + let averageAdultAge = CoreStore.queryValue( + From() + .select(Int.self, .average(\.age)) + .where(\.age > 18) + ) + ``` + - parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request. + - returns: the result of the the query as specified by the `QueryChainableBuilderType` + */ public static func queryValue(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType { return self.defaultStack.queryValue(clauseChain) @@ -291,7 +359,29 @@ public extension CoreStore { return self.defaultStack.queryAttributes(from, selectClause, queryClauses) } - // TODO: docs + /** + Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses. + + A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. + ``` + let results = CoreStore.queryAttributes( + From() + .select( + NSDictionary.self, + .attribute(\.age, as: "age"), + .count(\.age, as: "numberOfPeople") + ) + .groupBy(\.age) + ) + for dictionary in results! { + let age = dictionary["age"] as! Int + let count = dictionary["numberOfPeople"] as! Int + print("There are \(count) people who are \(age) years old." + } + ``` + - parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request. + - returns: the result of the the query as specified by the `QueryChainableBuilderType` + */ public static func queryAttributes(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary { return self.defaultStack.queryAttributes(clauseChain) diff --git a/Sources/DataStack+Querying.swift b/Sources/DataStack+Querying.swift index 409644e..341d519 100644 --- a/Sources/DataStack+Querying.swift +++ b/Sources/DataStack+Querying.swift @@ -109,7 +109,18 @@ extension DataStack: FetchableSource, QueryableSource { return self.mainContext.fetchOne(from, fetchClauses) } - // TODO: docs + /** + Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let youngestTeen = dataStack.fetchOne( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` + */ public func fetchOne(_ clauseChain: B) -> B.ObjectType? { CoreStore.assert( @@ -151,7 +162,18 @@ extension DataStack: FetchableSource, QueryableSource { return self.mainContext.fetchAll(from, fetchClauses) } - // TODO: docs + /** + Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let people = dataStack.fetchAll( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` + */ public func fetchAll(_ clauseChain: B) -> [B.ObjectType]? { CoreStore.assert( @@ -193,7 +215,18 @@ extension DataStack: FetchableSource, QueryableSource { return self.mainContext.fetchCount(from, fetchClauses) } - // TODO: docs + /** + Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let numberOfAdults = dataStack.fetchCount( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` + */ public func fetchCount(_ clauseChain: B) -> Int? { CoreStore.assert( @@ -235,7 +268,18 @@ extension DataStack: FetchableSource, QueryableSource { return self.mainContext.fetchObjectID(from, fetchClauses) } - // TODO: docs + /** + Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let youngestTeenID = dataStack.fetchObjectID( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` + */ public func fetchObjectID(_ clauseChain: B) -> NSManagedObjectID? { CoreStore.assert( @@ -277,7 +321,18 @@ extension DataStack: FetchableSource, QueryableSource { return self.mainContext.fetchObjectIDs(from, fetchClauses) } - // TODO: docs + /** + Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let idsOfAdults = dataStack.fetchObjectIDs( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` + */ public func fetchObjectIDs(_ clauseChain: B) -> [NSManagedObjectID]? { CoreStore.assert( @@ -328,7 +383,20 @@ extension DataStack: FetchableSource, QueryableSource { return self.mainContext.queryValue(from, selectClause, queryClauses) } - // TODO: docs + /** + Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses. + + A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. + ``` + let averageAdultAge = dataStack.queryValue( + From() + .select(Int.self, .average(\.age)) + .where(\.age > 18) + ) + ``` + - parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request. + - returns: the result of the the query as specified by the `QueryChainableBuilderType` + */ public func queryValue(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType { CoreStore.assert( @@ -376,7 +444,29 @@ extension DataStack: FetchableSource, QueryableSource { return self.mainContext.queryAttributes(from, selectClause, queryClauses) } - // TODO: docs + /** + Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses. + + A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. + ``` + let results = dataStack.queryAttributes( + From() + .select( + NSDictionary.self, + .attribute(\.age, as: "age"), + .count(\.age, as: "numberOfPeople") + ) + .groupBy(\.age) + ) + for dictionary in results! { + let age = dictionary["age"] as! Int + let count = dictionary["numberOfPeople"] as! Int + print("There are \(count) people who are \(age) years old." + } + ``` + - parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request. + - returns: the result of the the query as specified by the `QueryChainableBuilderType` + */ public func queryAttributes(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary { CoreStore.assert( diff --git a/Sources/FetchableSource.swift b/Sources/FetchableSource.swift index ce63ef3..ce4a425 100644 --- a/Sources/FetchableSource.swift +++ b/Sources/FetchableSource.swift @@ -84,7 +84,18 @@ public protocol FetchableSource: class { */ func fetchOne(_ from: From, _ fetchClauses: [FetchClause]) -> D? - // TODO: docs + /** + Fetches the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let youngestTeen = source.fetchOne( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the first `DynamicObject` instance that satisfies the specified `FetchChainableBuilderType` + */ func fetchOne(_ clauseChain: B) -> B.ObjectType? /** @@ -105,7 +116,18 @@ public protocol FetchableSource: class { */ func fetchAll(_ from: From, _ fetchClauses: [FetchClause]) -> [D]? - // TODO: docs + /** + Fetches all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let people = source.fetchAll( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: all `DynamicObject` instances that satisfy the specified `FetchChainableBuilderType` + */ func fetchAll(_ clauseChain: B) -> [B.ObjectType]? /** @@ -126,7 +148,18 @@ public protocol FetchableSource: class { */ func fetchCount(_ from: From, _ fetchClauses: [FetchClause]) -> Int? - // TODO: docs + /** + Fetches the number of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let numberOfAdults = source.fetchCount( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the number `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` + */ func fetchCount(_ clauseChain: B) -> Int? /** @@ -147,7 +180,18 @@ public protocol FetchableSource: class { */ func fetchObjectID(_ from: From, _ fetchClauses: [FetchClause]) -> NSManagedObjectID? - // TODO: docs + /** + Fetches the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let youngestTeenID = source.fetchObjectID( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the `NSManagedObjectID` for the first `DynamicObject` that satisfies the specified `FetchChainableBuilderType` + */ func fetchObjectID(_ clauseChain: B) -> NSManagedObjectID? /** @@ -168,7 +212,18 @@ public protocol FetchableSource: class { */ func fetchObjectIDs(_ from: From, _ fetchClauses: [FetchClause]) -> [NSManagedObjectID]? - // TODO: docs + /** + Fetches the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. + ``` + let idsOfAdults = source.fetchObjectIDs( + From() + .where(\.age > 18) + .orderBy(.ascending(\.age)) + ) + ``` + - parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses + - returns: the `NSManagedObjectID` for all `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` + */ func fetchObjectIDs(_ clauseChain: B) -> [NSManagedObjectID]? /** diff --git a/Sources/ImportableAttributeType.swift b/Sources/ImportableAttributeType.swift index 5c3dd18..6c78e15 100644 --- a/Sources/ImportableAttributeType.swift +++ b/Sources/ImportableAttributeType.swift @@ -163,12 +163,18 @@ extension UUID: ImportableAttributeType {} extension RawRepresentable where RawValue: ImportableAttributeType { + /** + Creates an instance of this type from its `QueryableNativeType` value. + */ @inline(__always) public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { return RawValue.cs_fromQueryableNativeType(value).flatMap({ self.init(rawValue: $0) }) } + /** + Creates `QueryableNativeType` value from this instance. + */ @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { diff --git a/Sources/Into.swift b/Sources/Into.swift index f016a05..f3c0d0a 100644 --- a/Sources/Into.swift +++ b/Sources/Into.swift @@ -64,11 +64,11 @@ public struct Into: Hashable { } /** - Initializes an `Into` clause with the specified entity type. + Initializes an `Into` clause with the specified entity type. This is useful for querying a subclass while binding the generic type with a base class. ``` - let person = transaction.create(Into(MyPersonEntity.self)) + let person = transaction.create(Into(MyEmployeeEntity.self)) ``` - - parameter entity: the `NSManagedObject` type to be created + - parameter entity: the `NSManagedObject` or `CoreStoreObject` type to be created */ public init(_ entity: D.Type) { @@ -80,7 +80,7 @@ public struct Into: Hashable { ``` let person = transaction.create(Into("Configuration1")) ``` - - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration. + - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s or `CoreStoreObject`'s entity type. Set to `nil` to use the default configuration. */ public init(_ configuration: ModelConfiguration) { @@ -88,12 +88,12 @@ public struct Into: Hashable { } /** - Initializes an `Into` clause with the specified entity type and configuration. + Initializes an `Into` clause with the specified entity type and configuration. This is useful for querying a subclass while binding the generic type with a base class. ``` - let person = transaction.create(Into(MyPersonEntity.self, "Configuration1")) + let person = transaction.create(Into(MyEmployeeEntity.self, "Configuration1")) ``` - - parameter entity: the `NSManagedObject` type to be created - - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s entity type. Set to `nil` to use the default configuration. + - parameter entity: the `NSManagedObject` or `CoreStoreObject` type to be created + - parameter configuration: the `NSPersistentStore` configuration name to associate the object to. This parameter is required if multiple configurations contain the created `NSManagedObject`'s or `CoreStoreObject`'s entity type. Set to `nil` to use the default configuration. */ public init(_ entity: D.Type, _ configuration: ModelConfiguration) { diff --git a/Sources/NSManagedObjectContext+Querying.swift b/Sources/NSManagedObjectContext+Querying.swift index 51f626b..706c07b 100644 --- a/Sources/NSManagedObjectContext+Querying.swift +++ b/Sources/NSManagedObjectContext+Querying.swift @@ -123,7 +123,6 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { return self.fetchOne(fetchRequest.dynamicCast()).flatMap(from.entityClass.cs_fromRaw) } - // TODO: docs @nonobjc public func fetchOne(_ clauseChain: B) -> B.ObjectType? { @@ -154,7 +153,6 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { return self.fetchAll(fetchRequest.dynamicCast())?.map(entityClass.cs_fromRaw) } - // TODO: docs @nonobjc public func fetchAll(_ clauseChain: B) -> [B.ObjectType]? { @@ -181,7 +179,6 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { return self.fetchCount(fetchRequest.dynamicCast()) } - // TODO: docs @nonobjc public func fetchCount(_ clauseChain: B) -> Int? { diff --git a/Sources/QueryableSource.swift b/Sources/QueryableSource.swift index b8fb498..292a530 100644 --- a/Sources/QueryableSource.swift +++ b/Sources/QueryableSource.swift @@ -58,7 +58,20 @@ public protocol QueryableSource: class { */ func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? - // TODO: docs + /** + Queries a property value or aggregate as specified by the `QueryChainableBuilderType` built from a chain of clauses. + + A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. + ``` + let averageAdultAge = dataStack.queryValue( + From() + .select(Int.self, .average(\.age)) + .where(\.age > 18) + ) + ``` + - parameter clauseChain: a `QueryChainableBuilderType` indicating the property/aggregate to fetch and the series of queries for the request. + - returns: the result of the the query as specified by the `QueryChainableBuilderType` + */ func queryValue(_ clauseChain: B) -> B.ResultType? where B.ResultType: QueryableAttributeType /** @@ -85,7 +98,29 @@ public protocol QueryableSource: class { */ func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> [[String: Any]]? - // TODO: docs + /** + Queries a dictionary of attribute values or as specified by the `QueryChainableBuilderType` built from a chain of clauses. + + A "query" differs from a "fetch" in that it only retrieves values already stored in the persistent store. As such, values from unsaved transactions or contexts will not be incorporated in the query result. + ``` + let results = source.queryAttributes( + From() + .select( + NSDictionary.self, + .attribute(\.age, as: "age"), + .count(\.age, as: "numberOfPeople") + ) + .groupBy(\.age) + ) + for dictionary in results! { + let age = dictionary["age"] as! Int + let count = dictionary["numberOfPeople"] as! Int + print("There are \(count) people who are \(age) years old." + } + ``` + - parameter clauseChain: a `QueryChainableBuilderType` indicating the properties to fetch and the series of queries for the request. + - returns: the result of the the query as specified by the `QueryChainableBuilderType` + */ func queryAttributes(_ clauseChain: B) -> [[String: Any]]? where B.ResultType == NSDictionary /** diff --git a/Sources/Relationship.swift b/Sources/Relationship.swift index 7720f71..744ec9a 100644 --- a/Sources/Relationship.swift +++ b/Sources/Relationship.swift @@ -234,6 +234,9 @@ public enum RelationshipContainer { // MARK: RelationshipProtocol + /** + The keyPath string represented by this property. Generally, there are more type-safe utilities for querying and other common tasks. + */ public let keyPath: KeyPathString internal let isToMany = false @@ -502,6 +505,9 @@ public enum RelationshipContainer { // MARK: RelationshipProtocol + /** + The keyPath string represented by this property. Generally, there are more type-safe utilities for querying and other common tasks. + */ public let keyPath: KeyPathString internal let isToMany = true @@ -776,6 +782,9 @@ public enum RelationshipContainer { // MARK: RelationshipProtocol + /** + The keyPath string represented by this property. Generally, there are more type-safe utilities for querying and other common tasks. + */ public let keyPath: KeyPathString internal let isToMany = true diff --git a/Sources/Transformable.swift b/Sources/Transformable.swift index c8896f7..59dc823 100644 --- a/Sources/Transformable.swift +++ b/Sources/Transformable.swift @@ -191,14 +191,17 @@ public enum TransformableContainer { // MARK: AttributeProtocol + + /** + The keyPath string represented by this property. Generally, there are more type-safe utilities for querying and other common tasks. + */ + public let keyPath: KeyPathString internal static var attributeType: NSAttributeType { return .transformableAttributeType } - public let keyPath: KeyPathString - internal let isOptional = false internal let isIndexed: Bool internal let isTransient: Bool @@ -420,6 +423,9 @@ public enum TransformableContainer { return .transformableAttributeType } + /** + The keyPath string represented by this property. Generally, there are more type-safe utilities for querying and other common tasks. + */ public let keyPath: KeyPathString internal let isOptional = true diff --git a/Sources/Value.swift b/Sources/Value.swift index e72debb..46db6f1 100644 --- a/Sources/Value.swift +++ b/Sources/Value.swift @@ -195,6 +195,9 @@ public enum ValueContainer { return V.cs_rawAttributeType } + /** + The keyPath string represented by this property. Generally, there are more type-safe utilities for querying and other common tasks. + */ public let keyPath: KeyPathString internal let isOptional = false @@ -421,7 +424,11 @@ public enum ValueContainer { return V.cs_rawAttributeType } + /** + The keyPath string represented by this property. Generally, there are more type-safe utilities for querying and other common tasks. + */ public let keyPath: KeyPathString + internal let isOptional = true internal let isIndexed: Bool internal let isTransient: Bool