はじめに
createdAtとupdatedAtはRDBだと自動的に生成してくれますが、Cloud Firestoreでは基本的にはクライアントからデータを登録する必要があります。
しかし、クライアント側で生成した日付データは改竄可能なので、Firestoreに適切ではない日付が登録される可能性があります。
そこでFirestore側には、ドキュメントがFirestoreに登録された時点での日付を設定できる関数が用意されています。
今回はその関数を使って、createdAtとupdatedAtを実装したいと思います。
ドキュメントの定義
まずはcreatedAtとupdatedAtを付与するドキュメントを下記のように定義しました。
import Firebase
struct SampleData: Codable {
internal let createdAt: Timestamp? = nil
internal let updatedAt: Timestamp? = nil
}
このSampleDataをFirestoreに登録した時に、createdAtとupdatedAtに登録した日付が保存されていることがゴールとなります。
Firestoreに登録された日付をcreatedAtとupdatedAtに設定する
Firestoreに登録された日付を設定するにはFieldValue.serverTimestamp関数を使用します。
この関数をメンバに持たせておくことで、そのデータがFirestoreに保存されたタイミングで、日付を自動的に設定してくれるというものです。
具体的には下記のように実装します。
struct SampleData: Codable {
internal let createdAt: Timestamp? = nil
internal let updatedAt: Timestamp? = nil
// ①
enum CodingKeys: String, CodingKey {
case createdAt
case updatedAt
}
}
extension SampleData {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
// ②
if self.createdAt == nil {
try container.encode(FieldValue.serverTimestamp(), forKey: .createdAt)
}
// ③
try container.encode(FieldValue.serverTimestamp(), forKey: .updatedAt)
}
}
①では、SampleDataをEncode&Decodeする対象のメンバを指定しています。
②のcreatedAtでは、登録された日付を保持したいので、登録時のみ(つまり初期値nilの場合)設定するようにしています。
③のupdateAtでは、更新されるたびに日付を上書きしたいので常にFieldValue.serverTimestamp()を設定します。
SampleDataを新規で登録する際はcreatedAtとupdatedAt両方に日付データが保存され、更新時にはupdatedAtだけ更新されるようになります。
EntityをEncode&Decodeする実装はこちらの記事で解説しています。