おはようこんにちはこんばんは。
RailsのActive RecordやLaravelのEloquentを普段使っていると、モデルにcreated_atやupdated_atが生えてきて勝手に更新してくれますがExposedの世界に来るとそれは自動的に出来ないので何とか出来るようにする方法を模索してみました。
流石にUpdateをする処理で毎回毎回手動で更新していたら超面倒くさいし、漏れも出てくるので仕組みで解決してあげます。
というわけでExposedのクラスを継承して早速実装してみる
今回はIdをPrimary Keyとして扱うIntIdTableを使いたいので、それらのクラスを継承してUpdate時の処理に自動的にタイムスタンプを更新させる処理を入れておきます。
abstract class ExposedTimestampIdTable(name: String = "", columnName: String = "id") : IntIdTable(name, columnName) {
val createdAt = datetimeWithTZ("created_at").clientDefault { Clock.System.now() }
val updatedAt = datetimeWithTZ("updated_at").clientDefault { Clock.System.now() }
}
abstract class ExposedTimestampIdEntity(id: EntityID<Int>, table: ExposedTimestampIdTable) : IntEntity(id) {
val createdAt by table.createdAt
var updatedAt by table.updatedAt
}
abstract class ExposedTimestampIdEntityClass<E : ExposedTimestampIdEntity>(table: ExposedTimestampIdTable) :
IntEntityClass<E>(table) {
init {
EntityHook.subscribe { action ->
if (action.changeType == EntityChangeType.Updated) {
action.toEntity(this)?.updatedAt = Clock.System.now()
}
}
}
}
今回は独自に実装した datetimeWithTZ
を使っているので、下の記事を参考に実装しておきましょう。
(タイムゾーン要らない場合は通常の datetime
にしておきましょう)
created_at
とupdated_at
は勝手に生やしておいて欲しいので、Table
と Entity
に createdAt
とupdatedAt
を実装して、 EntityClass
に自動的に updatedAt
を更新する処理を入れてあげます。
これらのクラスをどこかに実装しておきましょう。
使ってみる
object Users : ExposedTimestampIdTable("users") {
val name = varchar("name", 255)
val email = varchar("email", 255).nullable()
// 以下省略...
}
class User(id: EntityID<Int>) : ExposedTimestampIdEntity(id, Users) {
companion object : ExposedTimestampIdEntityClass<User>(Users)
var name by Users.name
var email by Users.email
// 以下省略...
}
いつも通り、IntIdTable
とIntEntity
とIntEntityClass
を使った時みたいに実装出来ますね!
さいごに
Exposedを使っているとActive RecordやEloquentで最初から出来ることが出来なかったりして、むむ???ってなることが多いですが、非常に拡張性が高く便利なライブラリなので使いやすいように育てながら使っていきましょう!