97 lines
2.3 KiB
Rust
97 lines
2.3 KiB
Rust
use serde_json;
|
|
use diesel::prelude::*;
|
|
use diesel::sql_types::Text;
|
|
use diesel::deserialize::FromSql;
|
|
use diesel::backend::Backend;
|
|
use crate::schema::history;
|
|
use crate::{DbConnection, QueryResult, Update};
|
|
|
|
#[derive(Debug, FromSqlRow)]
|
|
pub struct UpdateList(Vec<Update>);
|
|
|
|
// TODO: decide if updates is really optionnal or not
|
|
// (like if storing an event without update is usefull ?)
|
|
|
|
/// An event in history
|
|
#[derive(Debug, Queryable)]
|
|
pub struct Event {
|
|
id: i32,
|
|
player_id: i32,
|
|
event_date: String,
|
|
text: String,
|
|
updates: Option<UpdateList>,
|
|
}
|
|
|
|
impl Event {
|
|
pub fn name(&self) -> &str {
|
|
&self.text
|
|
}
|
|
|
|
/// TODO: why a move here ??
|
|
/// Undo all updates in a single transaction
|
|
pub fn undo(self, conn: &DbConnection) -> QueryResult<Self> {
|
|
conn.transaction(move || {
|
|
if let Some(ref updates) = self.updates {
|
|
for update in updates.0.iter() {
|
|
update.undo(conn, self.player_id)?;
|
|
}
|
|
diesel::delete(history::table.find(self.id)).execute(conn)?;
|
|
}
|
|
Ok(self)
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<DB: Backend> FromSql<Text, DB> for UpdateList
|
|
where
|
|
String: FromSql<Text, DB>,
|
|
{
|
|
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
|
|
let repr = String::from_sql(bytes)?;
|
|
Ok(UpdateList(serde_json::from_str::<Vec<Update>>(&repr)?))
|
|
}
|
|
}
|
|
|
|
|
|
#[derive(Debug, Insertable)]
|
|
#[table_name = "history"]
|
|
struct NewEvent<'a> {
|
|
player_id: i32,
|
|
text: &'a str,
|
|
updates: Option<String>,
|
|
}
|
|
|
|
|
|
/// Insert a new event
|
|
///
|
|
/// # Warning
|
|
/// This actually swallow up conversion errors
|
|
pub fn insert_event(conn: &DbConnection, id: i32, text: &str, updates: &Vec<Update>) -> QueryResult<Event> {
|
|
diesel::insert_into(history::table)
|
|
.values(&NewEvent {
|
|
player_id: id,
|
|
text,
|
|
updates: serde_json::to_string(updates).ok(),
|
|
})
|
|
.execute(conn)?;
|
|
history::table
|
|
.order(history::dsl::id.desc())
|
|
.first(conn)
|
|
}
|
|
|
|
pub fn get_last_of_player(conn: &DbConnection, id: i32) -> QueryResult<Event> {
|
|
history::table
|
|
.filter(history::dsl::player_id.eq(id))
|
|
.order(history::dsl::id.desc())
|
|
.first(conn)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
#[test]
|
|
fn test_insert_event_with_updates() {
|
|
|
|
}
|
|
}
|