From a4f5be93ef52340724674aaf3270137336e58f66 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Mon, 8 Jun 2020 12:11:34 -0700 Subject: [PATCH] Clean up todo example. --- examples/todo/src/main.rs | 43 ++++++++++++++++++++++++--------------- examples/todo/src/task.rs | 37 ++++++++++++++------------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/examples/todo/src/main.rs b/examples/todo/src/main.rs index 6b86c8f4..8bc3e29b 100644 --- a/examples/todo/src/main.rs +++ b/examples/todo/src/main.rs @@ -28,19 +28,25 @@ embed_migrations!(); pub struct DbConn(SqliteConnection); #[derive(Debug, Serialize)] -struct Context<'a>{ msg: Option<(&'a str, &'a str)>, tasks: Vec } +struct Context<'a> { + msg: Option<(&'a str, &'a str)>, + tasks: Vec +} impl<'a> Context<'a> { pub fn err(conn: &DbConn, msg: &'a str) -> Context<'a> { - Context{msg: Some(("error", msg)), tasks: Task::all(conn).unwrap_or_default()} + Context{msg: Some(("error", msg)), tasks: Task::all(conn).unwrap_or_default()} } pub fn raw(conn: &DbConn, msg: Option<(&'a str, &'a str)>) -> Context<'a> { match Task::all(conn) { - Ok(tasks) => Context{msg: msg, tasks}, - Err(_) => Context{ - msg: Some(("error", "Couldn't access the task database.")), - tasks: vec![] + Ok(tasks) => Context { msg, tasks}, + Err(e) => { + error_!("DB Task::all() error: {}", e); + Context { + msg: Some(("error", "Couldn't access the task database.")), + tasks: vec![] + } } } } @@ -52,7 +58,8 @@ fn new(todo_form: Form, conn: DbConn) -> Flash { if todo.description.is_empty() { Flash::error(Redirect::to("/"), "Description cannot be empty.") } else if let Err(e) = Task::insert(todo, &conn) { - Flash::error(Redirect::to("/"), &format!("Database error: {}", e)) + error_!("DB insertion error: {}", e); + Flash::error(Redirect::to("/"), "Todo could not be inserted due an internal error.") } else { Flash::success(Redirect::to("/"), "Todo successfully added.") } @@ -60,23 +67,27 @@ fn new(todo_form: Form, conn: DbConn) -> Flash { #[put("/")] fn toggle(id: i32, conn: DbConn) -> Result { - match Task::toggle_with_id(id, &conn) { - Ok(()) => Ok(Redirect::to("/")), - Err(e) => Err(Template::render("index", &Context::err(&conn, &format!("Couldn't toggle task: {}", e)))), - } + Task::toggle_with_id(id, &conn) + .map(|_| Redirect::to("/")) + .map_err(|e| { + error_!("DB toggle({}) error: {}", id, e); + Template::render("index", Context::err(&conn, "Failed to toggle task.")) + }) } #[delete("/")] fn delete(id: i32, conn: DbConn) -> Result, Template> { - match Task::delete_with_id(id, &conn) { - Ok(()) => Ok(Flash::success(Redirect::to("/"), "Todo was deleted.")), - Err(e) => Err(Template::render("index", &Context::err(&conn, &format!("Couldn't delete task: {}", e)))), - } + Task::delete_with_id(id, &conn) + .map(|_| Flash::success(Redirect::to("/"), "Todo was deleted.")) + .map_err(|e| { + error_!("DB deletion({}) error: {}", id, e); + Template::render("index", Context::err(&conn, "Failed to delete task.")) + }) } #[get("/")] fn index(msg: Option>, conn: DbConn) -> Template { - Template::render("index", &match msg { + Template::render("index", match msg { Some(ref msg) => Context::raw(&conn, Some((msg.name(), msg.msg()))), None => Context::raw(&conn, None), }) diff --git a/examples/todo/src/task.rs b/examples/todo/src/task.rs index 6eda6a4c..e10190aa 100644 --- a/examples/todo/src/task.rs +++ b/examples/todo/src/task.rs @@ -1,5 +1,4 @@ -use diesel::{self, result::Error as DieselError, prelude::*}; -type Result = std::result::Result; +use diesel::{self, result::QueryResult, prelude::*}; mod schema { table! { @@ -22,44 +21,38 @@ pub struct Task { pub completed: bool } -#[derive(FromForm)] +#[derive(Debug, FromForm)] pub struct Todo { pub description: String, } impl Task { - pub fn all(conn: &SqliteConnection) -> Result> { + pub fn all(conn: &SqliteConnection) -> QueryResult> { all_tasks.order(tasks::id.desc()).load::(conn) } - pub fn insert(todo: Todo, conn: &SqliteConnection) -> Result<()> { + /// Returns the number of affected rows: 1. + pub fn insert(todo: Todo, conn: &SqliteConnection) -> QueryResult { let t = Task { id: None, description: todo.description, completed: false }; - diesel::insert_into(tasks::table).values(&t).execute(conn)?; - - Ok(()) + diesel::insert_into(tasks::table).values(&t).execute(conn) } - pub fn toggle_with_id(id: i32, conn: &SqliteConnection) -> Result<()> { + /// Returns the number of affected rows: 1. + pub fn toggle_with_id(id: i32, conn: &SqliteConnection) -> QueryResult { let task = all_tasks.find(id).get_result::(conn)?; - let new_status = !task.completed; let updated_task = diesel::update(all_tasks.find(id)); - updated_task.set(task_completed.eq(new_status)).execute(conn)?; - - Ok(()) + updated_task.set(task_completed.eq(new_status)).execute(conn) } - pub fn delete_with_id(id: i32, conn: &SqliteConnection) -> Result<()> { - // `.execute` returns a usize representing the number of - // database rows affected by this modification. - // In a larger app these metrics may be useful, - // but for a simple example we'll ignore them. - diesel::delete(all_tasks.find(id)).execute(conn).map(|_| ()) + /// Returns the number of affected rows: 1. + pub fn delete_with_id(id: i32, conn: &SqliteConnection) -> QueryResult { + diesel::delete(all_tasks.find(id)).execute(conn) } + /// Returns the number of affected rows. #[cfg(test)] - pub fn delete_all(conn: &SqliteConnection) -> Result<()> { - // see comment in `.delete_with_id`. - diesel::delete(all_tasks).execute(conn).map(|_| ()) + pub fn delete_all(conn: &SqliteConnection) -> QueryResult { + diesel::delete(all_tasks).execute(conn) } }