Created
January 13, 2019 13:59
-
-
Save ljubinkovicd/d32afdabc18d91468ca33ba9805a8dea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Repositories | |
protocol Repository { | |
associatedtype Model | |
associatedtype Collection: Swift.Collection where Collection.Element == Model | |
func add(_ item: Model) -> Void | |
func add(_ items: Collection) -> Void | |
func update(_ item: Model) -> Void | |
func remove(_ item: Model) -> Void | |
func remove(specification: GenericSpecification<Model>) -> Void; | |
func query(specification: GenericSpecification<Model>) -> Observable<Model> | |
} | |
// One of many repositories... | |
class MessagesRepository: Repository { | |
func add(_ item: Message) {...} | |
func add(_ items: [Message]) {...} | |
func update(_ item: Message) {...} | |
func remove(_ item: Message) {...} | |
func remove(specification: GenericSpecification<Message>) -> Observable<Bool> { | |
return specification.toFirestoreQuery(Firestore.firestore()) | |
} | |
func query(specification: GenericSpecification<Message>) -> Observable<Message> { | |
return specification.toFirestoreQuery(Firestore.firestore()) | |
} | |
} | |
// Abstract specification(s) | |
protocol Specification {} | |
protocol FirestoreSpecification: Specification { | |
associatedtype Model | |
func toFirestoreQuery(_ firestore: Firestore) -> Observable<Model> | |
} | |
/* | |
We would use something like this if we decided to use something other than Firestore, such as Realm. | |
protocol RealmSpecification: Specification { | |
associatedtype Model | |
func toRealmQuery(_ realm: Realm) -> Observable<Model> | |
} | |
*/ | |
class GenericSpecification<T>: FirestoreSpecification { | |
func toFirestoreQuery(_ firestore: Firestore) -> Observable<T> { | |
fatalError("Must override toFirestoreQuery(_ firestore: Firestore) -> Observable<T>?") | |
} | |
} | |
// Concrete classes that conform to Specification | |
class AllMessagesSpecification: GenericSpecification<Message> { | |
override func toFirestoreQuery(_ firestore: Firestore) -> Observable<Message> {...} | |
} | |
class GetMessagesByUserIdSpecification: GenericSpecification<Message> { | |
private let id: String | |
init(id: String) { | |
self.id = id | |
} | |
override func toFirestoreQuery(_ firestore: Firestore) -> Observable<Message> {...} | |
} | |
class RemoveMessageByIdSpecification: GenericSpecification<Message> { | |
private let id: String | |
init(id: String) { | |
self.id = id | |
} | |
override func toFirestoreQuery(_ firestore: Firestore) -> Observable<Bool> {...} | |
} | |
// etc... | |
// Usage: | |
// This is just for explanation purposes | |
let messagesRepo: MessagesRepository = MessagesRepository() | |
// Get all messages | |
func observeMessages() -> Observable<Message> { | |
return messagesRepo | |
.query(specification: AllMessagesSpecification()) | |
} | |
// Get all messages for a specific user | |
func observeMessages(for userId: String) -> Observable<[Message]> { | |
return messagesRepo | |
.query(specification: GetMessagesByUserIdSpecification(id: userId)) | |
.toArray() | |
} | |
// Remove a message with id | |
func removeMessage(with id: String) -> Observable<Bool> { | |
return messagesRepo | |
.query(specification: RemoveMessageByIdSpecification(id: id)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment