Move save-using-cache code to DatabaseRelatedObjectsTable. Fix some build errors.

This commit is contained in:
Brent Simmons 2017-09-13 13:29:52 -07:00
parent 2df48bbd4d
commit 1cfa11d032
7 changed files with 127 additions and 83 deletions

View File

@ -298,8 +298,9 @@ private extension ArticlesTable {
saveRelatedObjectsForNewArticles(articles, database)
let databaseDictionaries = articles.map { $0.databaseDictionary() }
insertRows(databaseDictionaries, insertType: .orReplace, in: database)
if let databaseDictionaries = articles.databaseDictionaries() {
insertRows(databaseDictionaries, insertType: .orReplace, in: database)
}
}
func saveRelatedObjectsForNewArticles(_ articles: Set<Article>, _ database: FMDatabase) {

View File

@ -40,37 +40,12 @@ extension Article {
init(parsedItem: ParsedItem, accountID: String, feedID: String) {
let authors = Author.authorsWithParsedAuthors(parsedItem.authors)
let authors = parsedItem.authors?.authors()
let attachments = Attachment.attachmentsWithParsedAttachments(parsedItem.attachments)
self.init(accountID: accountID, articleID: parsedItem.syncServiceID, feedID: feedID, uniqueID: parsedItem.uniqueID, title: parsedItem.title, contentHTML: parsedItem.contentHTML, contentText: parsedItem.contentText, url: parsedItem.url, externalURL: parsedItem.externalURL, summary: parsedItem.summary, imageURL: parsedItem.imageURL, bannerImageURL: parsedItem.bannerImageURL, datePublished: parsedItem.datePublished, dateModified: parsedItem.dateModified, authors: authors, tags: parsedItem.tags, attachments: attachments, accountInfo: nil)
}
func databaseDictionary() -> NSDictionary {
let d = NSMutableDictionary()
d[DatabaseKey.articleID] = articleID
d[DatabaseKey.feedID] = feedID
d[DatabaseKey.uniqueID] = uniqueID
d.addOptionalString(title, DatabaseKey.title)
d.addOptionalString(contentHTML, DatabaseKey.contentHTML)
d.addOptionalString(contentText, DatabaseKey.contentText)
d.addOptionalString(url, DatabaseKey.url)
d.addOptionalString(externalURL, DatabaseKey.externalURL)
d.addOptionalString(summary, DatabaseKey.summary)
d.addOptionalString(imageURL, DatabaseKey.imageURL)
d.addOptionalString(bannerImageURL, DatabaseKey.bannerImageURL)
d.addOptionalDate(datePublished, DatabaseKey.datePublished)
d.addOptionalDate(dateModified, DatabaseKey.dateModified)
// TODO: accountInfo
return d.copy() as! NSDictionary
}
private func addPossibleStringChangeWithKeyPath(_ comparisonKeyPath: KeyPath<Article,String?>, _ otherArticle: Article, _ key: String, _ dictionary: NSMutableDictionary) {
if self[keyPath: comparisonKeyPath] != otherArticle[keyPath: comparisonKeyPath] {
@ -132,6 +107,31 @@ extension Article {
}
extension Article: DatabaseObject {
public func databaseDictionary() -> NSDictionary? {
let d = NSMutableDictionary()
d[DatabaseKey.articleID] = articleID
d[DatabaseKey.feedID] = feedID
d[DatabaseKey.uniqueID] = uniqueID
d.addOptionalString(title, DatabaseKey.title)
d.addOptionalString(contentHTML, DatabaseKey.contentHTML)
d.addOptionalString(contentText, DatabaseKey.contentText)
d.addOptionalString(url, DatabaseKey.url)
d.addOptionalString(externalURL, DatabaseKey.externalURL)
d.addOptionalString(summary, DatabaseKey.summary)
d.addOptionalString(imageURL, DatabaseKey.imageURL)
d.addOptionalString(bannerImageURL, DatabaseKey.bannerImageURL)
d.addOptionalDate(datePublished, DatabaseKey.datePublished)
d.addOptionalDate(dateModified, DatabaseKey.dateModified)
// TODO: accountInfo
return (d.copy() as! NSDictionary)
}
public var databaseID: String {
get {
@ -160,6 +160,11 @@ extension Set where Element == Article {
return self.map{ $0 as DatabaseObject }
}
func databaseDictionaries() -> [NSDictionary]? {
return self.flatMap { $0.databaseDictionary() }
}
}
private extension NSMutableDictionary {

View File

@ -23,22 +23,6 @@ extension ArticleStatus {
self.init(articleID: articleID, read: read, starred: starred, userDeleted: userDeleted, dateArrived: dateArrived, accountInfo: nil)
}
func databaseDictionary() -> NSDictionary {
let d = NSMutableDictionary()
d[DatabaseKey.articleID] = articleID
d[DatabaseKey.read] = read
d[DatabaseKey.starred] = starred
d[DatabaseKey.userDeleted] = userDeleted
d[DatabaseKey.dateArrived] = dateArrived
// if let accountInfo = accountInfo, let data = PropertyListTransformer.data(withPropertyList: accountInfo) {
// d[DatabaseKey.accountInfo] = data
// }
return d.copy() as! NSDictionary
}
}
extension ArticleStatus: DatabaseObject {
@ -48,4 +32,22 @@ extension ArticleStatus: DatabaseObject {
return articleID
}
}
public func databaseDictionary() -> NSDictionary? {
let d = NSMutableDictionary()
d[DatabaseKey.articleID] = articleID
d[DatabaseKey.read] = read
d[DatabaseKey.starred] = starred
d[DatabaseKey.userDeleted] = userDeleted
d[DatabaseKey.dateArrived] = dateArrived
// if let accountInfo = accountInfo, let data = PropertyListTransformer.data(withPropertyList: accountInfo) {
// d[DatabaseKey.accountInfo] = data
// }
return (d.copy() as! NSDictionary)
}
}

View File

@ -42,28 +42,6 @@ extension Attachment {
return attachments.isEmpty ? nil : Set(attachments)
}
func databaseDictionary() -> NSDictionary {
var d = NSMutableDictionary()
d[DatabaseKey.attachmentID] = attachmentID
d[DatabaseKey.url] = url
if let mimeType = mimeType {
d[DatabaseKey.mimeType] = mimeType
}
if let title = title {
d[DatabaseKey.title] = title
}
if let sizeInBytes = sizeInBytes {
d[DatabaseKey.sizeInBytes] = NSNumber(sizeInBytes)
}
if let durationInSeconds = durationInSeconds {
d[DatabaseKey.durationInSeconds] = NSNumber(durationInSeconds)
}
return d.copy() as! NSDictionary
}
}
private func optionalIntForColumn(_ row: FMResultSet, _ columnName: String) -> Int? {
@ -82,17 +60,41 @@ extension Attachment: DatabaseObject {
return attachmentID
}
}
func databaseDictionary() -> NSDictionary? {
let d = NSMutableDictionary()
d[DatabaseKey.attachmentID] = attachmentID
d[DatabaseKey.url] = url
if let mimeType = mimeType {
d[DatabaseKey.mimeType] = mimeType
}
if let title = title {
d[DatabaseKey.title] = title
}
if let sizeInBytes = sizeInBytes {
d[DatabaseKey.sizeInBytes] = NSNumber(value: sizeInBytes)
}
if let durationInSeconds = durationInSeconds {
d[DatabaseKey.durationInSeconds] = NSNumber(value: durationInSeconds)
}
return (d.copy() as! NSDictionary)
}
}
extension Set where Element == Attachment {
func databaseDictionaries() -> [NSDictionary] {
return self.map<NSDictionary> { $0.databaseDictionary() }
return self.flatMap { $0.databaseDictionary() }
}
func databaseObjects() -> [DatabaseObject] {
return self.map<DatabaseObject> { $0 as DatabaseObject }
return self.flatMap { $0 as DatabaseObject }
}
}

View File

@ -11,24 +11,22 @@ import Data
import RSDatabase
import RSParser
extension Author {
static func authorsWithParsedAuthors(_ parsedAuthors: Set<ParsedAuthor>?) -> Set<Author>? {
assert(!Thread.isMainThread)
guard let parsedAuthors = parsedAuthors else {
return nil
}
let authors = Set(parsedAuthors.flatMap { authorWithParsedAuthor($0) })
return authors.isEmpty ? nil : authors
}
}
// MARK: - DatabaseObject
extension Author: DatabaseObject {
public func databaseDictionary() -> NSDictionary? {
var d = NSMutableDictionary()
// TODO
if d.count < 1 {
return nil
}
return (d.copy() as! NSDictionary)
}
public var databaseID: String {
get {
@ -58,3 +56,14 @@ private extension Author {
}
}
// MARK: Author creation from Set<ParsedAuthor>
extension Set where Element == ParsedAuthor {
func authors() -> Set<Author>? {
let createdAuthors = Set(self.flatMap { Author(parsedAuthor: $0) })
return createdAuthors.isEmpty ? nil: createdAuthors
}
}

View File

@ -12,6 +12,8 @@ public protocol DatabaseObject {
var databaseID: String { get }
func databaseDictionary() -> NSDictionary?
func relatedObjectsWithName(_ name: String) -> [DatabaseObject]?
}
@ -48,4 +50,10 @@ extension Array where Element == DatabaseObject {
}
return false
}
func databaseDictionaries() -> [NSDictionary]? {
let dictionaries = self.flatMap{ $0.databaseDictionary() }
return dictionaries.isEmpty ? nil : dictionaries
}
}

View File

@ -62,4 +62,21 @@ public extension DatabaseRelatedObjectsTable {
return resultSet.flatMap(objectWithRow)
}
func save(_ objects: [DatabaseObject], in database: FMDatabase) {
// Objects in cache must already exist in database. Filter them out.
let objectsToSave = objects.filter { (object) -> Bool in
if let _ = cache[object.databaseID] {
return false
}
return true
}
cache.add(objectsToSave)
if let databaseDictionaries = objectsToSave.databaseDictionaries() {
insertRows(databaseDictionaries, insertType: .orIgnore, in: database)
}
}
}