Skip to content

Commit 784a405

Browse files
committed
Improved FetchableMember single boolean support
1 parent 6ba0076 commit 784a405

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

Sources/SafeFetching/Extensions/NSPredicate+Convenience.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,14 @@ extension NSPredicate {
2222
let predicate = predicate(SourceEntity.fetchableMembers)
2323
return predicate.nsValue
2424
}
25+
26+
/// Safely builds a predicate for a provided entity type.
27+
public static func safe<SourceEntity: Fetchable, TargetEntity: Fetchable>(
28+
on _: SourceEntity.Type,
29+
_ fetchableMember: (SourceEntity.FetchableMembers) -> FetchableMember<TargetEntity, Bool>
30+
) -> NSPredicate {
31+
let fetchableMember = fetchableMember(SourceEntity.fetchableMembers)
32+
let predicate = Builders.Predicate<TargetEntity>(identifier: fetchableMember.identifier, operatorString: "==", value: true)
33+
return predicate.nsValue
34+
}
2535
}

Sources/SafeFetching/Predicate/Types/CompoundPredicate.swift

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public func || <LE: NSManagedObject, RE: NSManagedObject>(
6060
)
6161
}
6262

63-
// MARK: - KeyPath <-> Predicate
63+
// MARK: - KeyPath <-> FetchableMember
6464

6565
public func && <LE: NSManagedObject, RE: NSManagedObject>(
6666
lhs: FetchableMember<LE, Bool>,
@@ -84,7 +84,7 @@ public func || <LE: NSManagedObject, RE: NSManagedObject>(
8484
)
8585
}
8686

87-
// MARK: - Predicate <-> KeyPath
87+
// MARK: - Predicate <-> FetchableMember
8888

8989
public func && <LE: NSManagedObject, RE: NSManagedObject>(
9090
lhs: Builders.Predicate<LE>,
@@ -93,7 +93,7 @@ public func && <LE: NSManagedObject, RE: NSManagedObject>(
9393
Builders.CompoundPredicate(
9494
joinOperator: .and,
9595
leftPredicate: lhs,
96-
rightPredicate: Builders.Predicate<RE>(identifier: rhs.identifier)
96+
rightPredicate: Builders.Predicate<RE>(identifier: rhs.identifier)
9797
)
9898
}
9999

@@ -104,6 +104,30 @@ public func || <LE: NSManagedObject, RE: NSManagedObject>(
104104
Builders.CompoundPredicate(
105105
joinOperator: .or,
106106
leftPredicate: lhs,
107-
rightPredicate: Builders.Predicate<RE>(identifier: rhs.identifier)
107+
rightPredicate: Builders.Predicate<RE>(identifier: rhs.identifier)
108+
)
109+
}
110+
111+
// MARK: - FetchableMember <-> FetchableMember
112+
113+
public func && <LE: NSManagedObject, RE: NSManagedObject>(
114+
lhs: FetchableMember<LE, Bool>,
115+
rhs: FetchableMember<RE, Bool>
116+
) -> Builders.CompoundPredicate<LE, RE> {
117+
Builders.CompoundPredicate(
118+
joinOperator: .and,
119+
leftPredicate: Builders.Predicate<LE>(identifier: lhs.identifier),
120+
rightPredicate: Builders.Predicate<RE>(identifier: rhs.identifier)
121+
)
122+
}
123+
124+
public func || <LE: NSManagedObject, RE: NSManagedObject>(
125+
lhs: FetchableMember<LE, Bool>,
126+
rhs: FetchableMember<RE, Bool>
127+
) -> Builders.CompoundPredicate<LE, RE> {
128+
Builders.CompoundPredicate(
129+
joinOperator: .or,
130+
leftPredicate: Builders.Predicate<LE>(identifier: lhs.identifier),
131+
rightPredicate: Builders.Predicate<RE>(identifier: rhs.identifier)
108132
)
109133
}

Tests/SafeFetchingTests/BooleanPredicateBuilderTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,20 @@ extension BooleanPredicates {
130130
}
131131
}
132132

133+
// MARK: - NSPredicate
134+
135+
extension BooleanPredicates {
136+
137+
@Test("NSPredicate.safe")
138+
func nsPredicateSafe() {
139+
var predicate = NSPredicate.safe(on: StubEntity.self) { $0.isAdmin }
140+
#expect(predicate.predicateFormat == "isAdmin == 1")
141+
142+
predicate = NSPredicate.safe(on: StubEntity.self) { $0.stubRelationship.isDownloaded }
143+
#expect(predicate.predicateFormat == "stubRelationship.isDownloaded == 1")
144+
}
145+
}
146+
133147
// MARK: - Helpers
134148

135149
extension BooleanPredicates {
@@ -184,11 +198,13 @@ extension BooleanPredicates {
184198
final class StubEntityBis: NSManagedObject, Fetchable {
185199

186200
@objc var property: String? = ""
201+
@objc var isDownloaded: Bool = false
187202

188203
static let fetchableMembers = FetchableMembers()
189204

190205
struct FetchableMembers {
191206
let property = FetchableMember<StubEntityBis, String?>(identifier: "property")
207+
let isDownloaded = FetchableMember<StubEntityBis, Bool>(identifier: "isDownloaded")
192208
}
193209
}
194210
}

Tests/SafeFetchingTests/CompoundPredicateBuilderTests.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ extension CompoundPredicates {
7474
func orSingleBooleanLeft() {
7575
testNSFormat({ $0.name == "Toto" || $0.isDownloaded }, expecting: #"name == "Toto" OR isDownloaded == 1"#)
7676
}
77+
78+
@Test("Both Boolean FetchableMember")
79+
func bothBooleanFetchableMember() {
80+
testNSFormat({ $0.isDownloaded && $0.isDownloaded }, expecting: #"isDownloaded == 1 AND isDownloaded == 1"#)
81+
testNSFormat({ $0.isDownloaded || $0.isDownloaded }, expecting: #"isDownloaded == 1 OR isDownloaded == 1"#)
82+
}
7783
}
7884

7985
// MARK: - Helpers

0 commit comments

Comments
 (0)