🦀
Rust Diesel で enum を扱う
やりたいこと
Rust Diesel で Enum を使用してデータを保存します。
Usecase
スケジュール管理のアプリで Event model に繰り返しか単発かを判定する RepeatType
Enum の実装。
実装
Mysql
repeat_type
が永続化させるためのフィールドです。
今回は TINYINT
型でフィールドを作成します。
CREATE TABLE IF NOT EXISTS events (
id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
title VARCHAR(255) NOT NULL,
start_at TIMESTAMP NOT NULL,
end_at TIMESTAMP NOT NULL,
repeat_type TINYINT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMP
);
RepeatType enum model (Rust)
RepeatType
という enum の実装します。
RepeatType
に以下の関数を implement します。
- from: Applicationから渡される値から
RepeatType
を返します。 - from_sql: SQLのデータ取得時にデータから
RepeatType
を返します。 - to_sql:
RepeatType
を保存するときにSQLに対応するために値を変換します。
#[derive(Debug, AsExpression, FromSqlRow, Deserialize, Serialize)]
#[diesel(sql_type = diesel::sql_types::TinyInt)]
pub enum RepeatType {
Once = 1,
Recurrence = 2,
}
impl From<i8> for RepeatType {
fn from(i: i8) -> Self {
match i {
1 => RepeatType::Once,
2 => RepeatType::Recurrence,
_ => panic!("Invalid value for RepeatType"),
}
}
}
impl<DB: Backend> FromSql<TinyInt, DB> for RepeatType
where
DB: Backend,
i8: FromSql<TinyInt, DB>,
{
fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
match i8::from_sql(bytes)? {
1 => Ok(RepeatType::Once),
2 => Ok(RepeatType::Recurrence),
x => Err(format!("Unrecognized variant {}", x).into()),
}
}
}
impl<DB> ToSql<TinyInt, DB> for RepeatType
where
DB: Backend,
i8: ToSql<TinyInt, DB>,
{
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> serialize::Result {
match self {
RepeatType::Once => 1.to_sql(out),
RepeatType::Recurrence => 2.to_sql(out),
}
}
}
Event model (Rust)
Event model に Repeat Type
を実装します。
#[derive(Identifiable, Queryable, Debug, Serialize)]
#[diesel(table_name = events)]
#[diesel(check_for_backend(diesel::mysql::Mysql))]
pub struct Event {
pub id: String,
pub title: String,
pub start_at: NaiveDateTime,
pub end_at: NaiveDateTime,
pub repeat_type: RepeatType,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub deleted_at: Option<NaiveDateTime>,
}
代案
diesel-derive-enum
という crate もあるが自分の環境だと思うように動作しなかったので今回は使用してませんが、上記の実装を簡単にしてくれる crate なのでおすすめです。
Discussion