mirror of https://github.com/rwf2/Rocket.git
Clean up todo example.
This commit is contained in:
parent
da34b66eb4
commit
a4f5be93ef
|
@ -28,7 +28,10 @@ embed_migrations!();
|
||||||
pub struct DbConn(SqliteConnection);
|
pub struct DbConn(SqliteConnection);
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
struct Context<'a>{ msg: Option<(&'a str, &'a str)>, tasks: Vec<Task> }
|
struct Context<'a> {
|
||||||
|
msg: Option<(&'a str, &'a str)>,
|
||||||
|
tasks: Vec<Task>
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Context<'a> {
|
impl<'a> Context<'a> {
|
||||||
pub fn err(conn: &DbConn, msg: &'a str) -> Context<'a> {
|
pub fn err(conn: &DbConn, msg: &'a str) -> Context<'a> {
|
||||||
|
@ -37,13 +40,16 @@ impl<'a> Context<'a> {
|
||||||
|
|
||||||
pub fn raw(conn: &DbConn, msg: Option<(&'a str, &'a str)>) -> Context<'a> {
|
pub fn raw(conn: &DbConn, msg: Option<(&'a str, &'a str)>) -> Context<'a> {
|
||||||
match Task::all(conn) {
|
match Task::all(conn) {
|
||||||
Ok(tasks) => Context{msg: msg, tasks},
|
Ok(tasks) => Context { msg, tasks},
|
||||||
Err(_) => Context{
|
Err(e) => {
|
||||||
|
error_!("DB Task::all() error: {}", e);
|
||||||
|
Context {
|
||||||
msg: Some(("error", "Couldn't access the task database.")),
|
msg: Some(("error", "Couldn't access the task database.")),
|
||||||
tasks: vec![]
|
tasks: vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/", data = "<todo_form>")]
|
#[post("/", data = "<todo_form>")]
|
||||||
|
@ -52,7 +58,8 @@ fn new(todo_form: Form<Todo>, conn: DbConn) -> Flash<Redirect> {
|
||||||
if todo.description.is_empty() {
|
if todo.description.is_empty() {
|
||||||
Flash::error(Redirect::to("/"), "Description cannot be empty.")
|
Flash::error(Redirect::to("/"), "Description cannot be empty.")
|
||||||
} else if let Err(e) = Task::insert(todo, &conn) {
|
} 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 {
|
} else {
|
||||||
Flash::success(Redirect::to("/"), "Todo successfully added.")
|
Flash::success(Redirect::to("/"), "Todo successfully added.")
|
||||||
}
|
}
|
||||||
|
@ -60,23 +67,27 @@ fn new(todo_form: Form<Todo>, conn: DbConn) -> Flash<Redirect> {
|
||||||
|
|
||||||
#[put("/<id>")]
|
#[put("/<id>")]
|
||||||
fn toggle(id: i32, conn: DbConn) -> Result<Redirect, Template> {
|
fn toggle(id: i32, conn: DbConn) -> Result<Redirect, Template> {
|
||||||
match Task::toggle_with_id(id, &conn) {
|
Task::toggle_with_id(id, &conn)
|
||||||
Ok(()) => Ok(Redirect::to("/")),
|
.map(|_| Redirect::to("/"))
|
||||||
Err(e) => Err(Template::render("index", &Context::err(&conn, &format!("Couldn't toggle task: {}", e)))),
|
.map_err(|e| {
|
||||||
}
|
error_!("DB toggle({}) error: {}", id, e);
|
||||||
|
Template::render("index", Context::err(&conn, "Failed to toggle task."))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[delete("/<id>")]
|
#[delete("/<id>")]
|
||||||
fn delete(id: i32, conn: DbConn) -> Result<Flash<Redirect>, Template> {
|
fn delete(id: i32, conn: DbConn) -> Result<Flash<Redirect>, Template> {
|
||||||
match Task::delete_with_id(id, &conn) {
|
Task::delete_with_id(id, &conn)
|
||||||
Ok(()) => Ok(Flash::success(Redirect::to("/"), "Todo was deleted.")),
|
.map(|_| Flash::success(Redirect::to("/"), "Todo was deleted."))
|
||||||
Err(e) => Err(Template::render("index", &Context::err(&conn, &format!("Couldn't delete task: {}", e)))),
|
.map_err(|e| {
|
||||||
}
|
error_!("DB deletion({}) error: {}", id, e);
|
||||||
|
Template::render("index", Context::err(&conn, "Failed to delete task."))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
fn index(msg: Option<FlashMessage<'_, '_>>, conn: DbConn) -> Template {
|
fn index(msg: Option<FlashMessage<'_, '_>>, conn: DbConn) -> Template {
|
||||||
Template::render("index", &match msg {
|
Template::render("index", match msg {
|
||||||
Some(ref msg) => Context::raw(&conn, Some((msg.name(), msg.msg()))),
|
Some(ref msg) => Context::raw(&conn, Some((msg.name(), msg.msg()))),
|
||||||
None => Context::raw(&conn, None),
|
None => Context::raw(&conn, None),
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use diesel::{self, result::Error as DieselError, prelude::*};
|
use diesel::{self, result::QueryResult, prelude::*};
|
||||||
type Result<T> = std::result::Result<T, DieselError>;
|
|
||||||
|
|
||||||
mod schema {
|
mod schema {
|
||||||
table! {
|
table! {
|
||||||
|
@ -22,44 +21,38 @@ pub struct Task {
|
||||||
pub completed: bool
|
pub completed: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromForm)]
|
#[derive(Debug, FromForm)]
|
||||||
pub struct Todo {
|
pub struct Todo {
|
||||||
pub description: String,
|
pub description: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Task {
|
impl Task {
|
||||||
pub fn all(conn: &SqliteConnection) -> Result<Vec<Task>> {
|
pub fn all(conn: &SqliteConnection) -> QueryResult<Vec<Task>> {
|
||||||
all_tasks.order(tasks::id.desc()).load::<Task>(conn)
|
all_tasks.order(tasks::id.desc()).load::<Task>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(todo: Todo, conn: &SqliteConnection) -> Result<()> {
|
/// Returns the number of affected rows: 1.
|
||||||
|
pub fn insert(todo: Todo, conn: &SqliteConnection) -> QueryResult<usize> {
|
||||||
let t = Task { id: None, description: todo.description, completed: false };
|
let t = Task { id: None, description: todo.description, completed: false };
|
||||||
diesel::insert_into(tasks::table).values(&t).execute(conn)?;
|
diesel::insert_into(tasks::table).values(&t).execute(conn)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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<usize> {
|
||||||
let task = all_tasks.find(id).get_result::<Task>(conn)?;
|
let task = all_tasks.find(id).get_result::<Task>(conn)?;
|
||||||
|
|
||||||
let new_status = !task.completed;
|
let new_status = !task.completed;
|
||||||
let updated_task = diesel::update(all_tasks.find(id));
|
let updated_task = diesel::update(all_tasks.find(id));
|
||||||
updated_task.set(task_completed.eq(new_status)).execute(conn)?;
|
updated_task.set(task_completed.eq(new_status)).execute(conn)
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_with_id(id: i32, conn: &SqliteConnection) -> Result<()> {
|
/// Returns the number of affected rows: 1.
|
||||||
// `.execute` returns a usize representing the number of
|
pub fn delete_with_id(id: i32, conn: &SqliteConnection) -> QueryResult<usize> {
|
||||||
// database rows affected by this modification.
|
diesel::delete(all_tasks.find(id)).execute(conn)
|
||||||
// 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.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn delete_all(conn: &SqliteConnection) -> Result<()> {
|
pub fn delete_all(conn: &SqliteConnection) -> QueryResult<usize> {
|
||||||
// see comment in `.delete_with_id`.
|
diesel::delete(all_tasks).execute(conn)
|
||||||
diesel::delete(all_tasks).execute(conn).map(|_| ())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue