Section 5/181 menit
5. @Relationship Lanjutan: Delete Rules dan Inverse
5. @Relationship Lanjutan: Delete Rules dan Inverse
Delete Rules
swift
@Model
final class Author {
var name: String
// .cascade: hapus Author → hapus semua Post-nya
@Relationship(deleteRule: .cascade, inverse: \Post.author)
var posts: [Post] = []
init(name: String) { self.name = name }
}
@Model
final class Post {
var title: String
var body: String
// .nullify (default): hapus Author → Post.author = nil
var author: Author?
// .deny: hapus Tag gagal jika masih ada Post yang memakai tag ini
@Relationship(deleteRule: .deny, inverse: \Tag.posts)
var tags: [Tag] = []
init(title: String, body: String) {
self.title = title
self.body = body
}
}
@Model
final class Tag {
@Attribute(.unique) var name: String
var posts: [Post] = []
init(name: String) { self.name = name }
}
Delete Rules Summary
| Rule | Perilaku saat parent dihapus | Kapan digunakan |
|---|---|---|
.cascade |
Semua children ikut terhapus | Post → Comments (comment tidak berguna tanpa post) |
.nullify |
Children masih ada, foreign key jadi nil | Author → Posts (post tetap ada meski author dihapus) |
.deny |
Penghapusan gagal jika masih ada children | Category → Products (tidak boleh hapus category yang masih dipakai) |
.noAction |
Tidak ada tindakan (data inconsistency risk) | Jarang dipakai, untuk kontrol manual |
Ordered Relationships
swift
@Model
final class Playlist {
var name: String
// Ordered relationship — urutan dipertahankan
@Relationship(deleteRule: .cascade, minimumModelCount: 0, maximumModelCount: nil)
var tracks: [Track] = []
init(name: String) { self.name = name }
func addTrack(_ track: Track, at index: Int? = nil) {
if let index {
tracks.insert(track, at: index)
} else {
tracks.append(track)
}
}
func moveTrack(from source: Int, to destination: Int) {
let track = tracks.remove(at: source)
tracks.insert(track, at: destination)
}
}
@Model
final class Track {
var title: String
var duration: TimeInterval
var playlist: Playlist?
init(title: String, duration: TimeInterval) {
self.title = title
self.duration = duration
}
}
Reciprocal (Circular) Relationships
swift
// Graph relationship: User bisa follow User lain
@Model
final class UserProfile {
@Attribute(.unique) var username: String
var displayName: String
// following: user yang kamu follow
@Relationship(deleteRule: .nullify, inverse: \UserProfile.followers)
var following: [UserProfile] = []
// followers: user yang follow kamu (inverse dari following)
var followers: [UserProfile] = []
init(username: String, displayName: String) {
self.username = username
self.displayName = displayName
}
func follow(_ other: UserProfile) {
guard !following.contains(where: { $0.username == other.username }) else { return }
following.append(other)
// followers di other otomatis terupdate karena inverse relationship
}
}