Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove context from a few service types #20010

Merged
merged 8 commits into from
Jan 30, 2023

Conversation

crazytonyli
Copy link
Contributor

@crazytonyli crazytonyli commented Jan 26, 2023

Use CoreDataStack instead of NSManagedObjectContext in a few service types. See the "Issue" and "Proposal" sections of #19893 for rational behind this change.

Regression Notes

  1. Potential unintended areas of impact
    None

  2. What I did to test those areas of impact (or what existing automated tests I relied on)
    None

  3. What automated tests I added (or what prevented me from doing so)
    None

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding unit tests for my changes.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Jan 26, 2023

You can test the changes in WordPress from this Pull Request by:
  • Clicking here or scanning the QR code below to access App Center
  • Then installing the build number pr20010-2b5f7d0 on your iPhone

If you need access to App Center, please ask a maintainer to add you.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Jan 26, 2023

You can test the changes in Jetpack from this Pull Request by:
  • Clicking here or scanning the QR code below to access App Center
  • Then installing the build number pr20010-2b5f7d0 on your iPhone

If you need access to App Center, please ask a maintainer to add you.

@crazytonyli crazytonyli force-pushed the remove-context-from-a-few-service-types branch from d2f1d2a to e667bcb Compare January 27, 2023 08:02
@crazytonyli crazytonyli self-assigned this Jan 27, 2023
@crazytonyli crazytonyli added the Core Data Issues related to Core Data label Jan 27, 2023
@crazytonyli crazytonyli added this to the 21.7 milestone Jan 27, 2023
@crazytonyli crazytonyli marked this pull request as ready for review January 27, 2023 08:10
@@ -115,8 +111,7 @@ class SiteManagementServiceTests: CoreDataTestCase {
mockRemoteService.successBlockPassedIn?()
waitForExpectations(timeout: 2, handler: nil)

let shouldBeRemoved = try? context.existingObject(with: blogObjectID)
XCTAssertFalse(shouldBeRemoved != nil, "Blog was not removed")
try XCTAssertEqual(context.count(for: Blog.fetchRequest()), 0)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this assertion here because the blog will exist in the context until context.save() is called. Using NSFetchRequest is a more accurate way to check if the object is deleted from the database.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good 👍

Do you know whether there are more of this kind of tests that we should consider upgrading (in a dedicated all-in-one PR)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, this is the first time I ran into this kind of issue, maybe I'll find more? I can only notice them if I happen to look at the test case or the test case fails during development. 😄

Copy link
Contributor

@mokagio mokagio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only nitpicks 👍

WordPress/Classes/Models/Role.swift Outdated Show resolved Hide resolved
suggestion = NSEntityDescription.insertNewObject(forEntityName: ReaderSearchSuggestion.classNameWithoutNamespaces(),
into: managedObjectContext) as? ReaderSearchSuggestion
suggestion?.searchPhrase = phrase
self.coreDataStack.performAndSave { context in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Is it necessary to access coreDataStack from self here?

Suggested change
self.coreDataStack.performAndSave { context in
coreDataStack.performAndSave { context in

@@ -30,71 +40,35 @@ import CocoaLumberjack
///
/// - Returns: A matching search phrase or nil.
///
@objc func findSuggestionForPhrase(_ phrase: String) -> ReaderSearchSuggestion? {
private func findSuggestionForPhrase(_ phrase: String, in context: NSManagedObjectContext) -> ReaderSearchSuggestion? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick / Out of scope convention question:

This method use findSuggestionForPhrase(_ phrase: String, ... a similar method in a different file from this diff use lookup(withBlogID blogID: String, .... The style of the two is inconsistent.

I personally prefer the latter, but I think the Swift API Design Guidelines would recommend using the former, as the argument is part of a prepositional phrase.

image

"For" and "with" are both prepositions, ChatGPT told me so:

Screenshot 2023-01-30 at 4 46 46 pm

To be honest, I feel like breaking from the guidelines in this case. I find more value in not having to think whether to name the first parameter or not vs. using what might be better English grammar in the API names.

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the Swift API Design Guidelines would recommend using the former

If I understand it correctly, using the former is a case of exception where there are two or more arguments? i.e. findSuggestionFor(phrase: "hello", author: "Tony")

The signature findSuggestion(forPhrase: "hello", in: context) looks pretty nature to me, so I've changed it in 754dae1

Comment on lines 62 to 70
var suggestions = [ReaderSearchSuggestion]()
do {
suggestions = try context.fetch(fetchRequest) as! [ReaderSearchSuggestion]
} catch let error as NSError {
DDLogError("Error fetching search suggestion : \(error.localizedDescription)")
}
for suggestion in suggestions {
context.delete(suggestion)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Have you considered moving the for loop inside the do catch to avoid declaring a var?

Suggested change
var suggestions = [ReaderSearchSuggestion]()
do {
suggestions = try context.fetch(fetchRequest) as! [ReaderSearchSuggestion]
} catch let error as NSError {
DDLogError("Error fetching search suggestion : \(error.localizedDescription)")
}
for suggestion in suggestions {
context.delete(suggestion)
}
do {
try (context.fetch(fetchRequest) as! [ReaderSearchSuggestion]).forEach { context.delete($0) }
} catch let error as NSError {
DDLogError("Error fetching search suggestion : \(error.localizedDescription)")
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Addressed in 2b5f7d0

roleService.fetchRoles(success: {_ in
roleService.fetchRoles(success: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💅 👍

guard let blog = blog,
let service = RoleService(blog: blog, context: viewContext) else {
return nil
guard let blog = blog else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to suggest guard let blog else but I got annoyed at myself for being so pedantic about things that could be automated...

SwiftLint supports this, I should add the check to our https://github.com/Automattic/swiftlint-config and integrate it here...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries. It's always good to have cleaner code. Updated in 4412706

@@ -115,8 +111,7 @@ class SiteManagementServiceTests: CoreDataTestCase {
mockRemoteService.successBlockPassedIn?()
waitForExpectations(timeout: 2, handler: nil)

let shouldBeRemoved = try? context.existingObject(with: blogObjectID)
XCTAssertFalse(shouldBeRemoved != nil, "Blog was not removed")
try XCTAssertEqual(context.count(for: Blog.fetchRequest()), 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good 👍

Do you know whether there are more of this kind of tests that we should consider upgrading (in a dedicated all-in-one PR)?

@crazytonyli crazytonyli merged commit f164645 into trunk Jan 30, 2023
@crazytonyli crazytonyli deleted the remove-context-from-a-few-service-types branch January 30, 2023 22:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Core Data Issues related to Core Data
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants