Use connection pool in todo example.

This commit is contained in:
Sergio Benitez 2017-02-02 17:38:36 -08:00
parent 7f9ced7db3
commit a15002877d
3 changed files with 32 additions and 30 deletions

View File

@ -9,8 +9,10 @@ rocket_codegen = { path = "../../codegen" }
serde = "0.9"
serde_json = "0.9"
serde_derive = "0.9"
r2d2 = "0.7"
diesel = { version = "0.10", features = ["sqlite"] }
diesel_codegen = { version = "0.10", features = ["sqlite"] }
r2d2-diesel = { version = "0.10", features = ["sqlite"] }
[dependencies.rocket_contrib]
path = "../../contrib"

View File

@ -7,34 +7,38 @@ extern crate serde_json;
#[macro_use] extern crate diesel_codegen;
#[macro_use] extern crate serde_derive;
extern crate rocket_contrib;
extern crate r2d2;
extern crate r2d2_diesel;
mod static_files;
mod task;
mod db;
use rocket::request::{Form, FlashMessage};
use rocket::response::{Flash, Redirect};
use rocket_contrib::Template;
use task::Task;
#[derive(Debug, Serialize)]
struct Context<'a, 'b>{ msg: Option<(&'a str, &'b str)>, tasks: Vec<Task> }
impl<'a, 'b> Context<'a, 'b> {
pub fn err(msg: &'a str) -> Context<'static, 'a> {
Context{msg: Some(("error", msg)), tasks: Task::all()}
pub fn err(conn: &db::Conn, msg: &'a str) -> Context<'static, 'a> {
Context{msg: Some(("error", msg)), tasks: Task::all(conn)}
}
pub fn raw(msg: Option<(&'a str, &'b str)>) -> Context<'a, 'b> {
Context{msg: msg, tasks: Task::all()}
pub fn raw(conn: &db::Conn, msg: Option<(&'a str, &'b str)>) -> Context<'a, 'b> {
Context{msg: msg, tasks: Task::all(conn)}
}
}
#[post("/", data = "<todo_form>")]
fn new(todo_form: Form<Task>) -> Flash<Redirect> {
fn new(todo_form: Form<Task>, conn: db::Conn) -> Flash<Redirect> {
let todo = todo_form.into_inner();
if todo.description.is_empty() {
Flash::error(Redirect::to("/"), "Description cannot be empty.")
} else if todo.insert() {
} else if todo.insert(&conn) {
Flash::success(Redirect::to("/"), "Todo successfully added.")
} else {
Flash::error(Redirect::to("/"), "Whoops! The server failed.")
@ -42,33 +46,34 @@ fn new(todo_form: Form<Task>) -> Flash<Redirect> {
}
#[put("/<id>")]
fn toggle(id: i32) -> Result<Redirect, Template> {
if Task::toggle_with_id(id) {
fn toggle(id: i32, conn: db::Conn) -> Result<Redirect, Template> {
if Task::toggle_with_id(id, &conn) {
Ok(Redirect::to("/"))
} else {
Err(Template::render("index", &Context::err("Couldn't toggle task.")))
Err(Template::render("index", &Context::err(&conn, "Couldn't toggle task.")))
}
}
#[delete("/<id>")]
fn delete(id: i32) -> Result<Flash<Redirect>, Template> {
if Task::delete_with_id(id) {
fn delete(id: i32, conn: db::Conn) -> Result<Flash<Redirect>, Template> {
if Task::delete_with_id(id, &conn) {
Ok(Flash::success(Redirect::to("/"), "Todo was deleted."))
} else {
Err(Template::render("index", &Context::err("Couldn't delete task.")))
Err(Template::render("index", &Context::err(&conn, "Couldn't delete task.")))
}
}
#[get("/")]
fn index(msg: Option<FlashMessage>) -> Template {
fn index(msg: Option<FlashMessage>, conn: db::Conn) -> Template {
Template::render("index", &match msg {
Some(ref msg) => Context::raw(Some((msg.name(), msg.msg()))),
None => Context::raw(None),
Some(ref msg) => Context::raw(&conn, Some((msg.name(), msg.msg()))),
None => Context::raw(&conn, None),
})
}
fn main() {
rocket::ignite()
.manage(db::init_pool())
.mount("/", routes![index, static_files::all])
.mount("/todo/", routes![new, toggle, delete])
.launch();

View File

@ -1,19 +1,14 @@
use diesel;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;
use self::schema::tasks;
use self::schema::tasks::dsl::{tasks as all_tasks, completed as task_completed};
const DATABASE_FILE: &'static str = env!("DATABASE_URL");
mod schema {
infer_schema!("env:DATABASE_URL");
}
fn db() -> SqliteConnection {
SqliteConnection::establish(DATABASE_FILE).expect("Failed to connect to db.")
}
#[table_name = "tasks"]
#[derive(Serialize, Queryable, Insertable, FromForm, Debug, Clone)]
pub struct Task {
@ -23,27 +18,27 @@ pub struct Task {
}
impl Task {
pub fn all() -> Vec<Task> {
all_tasks.order(tasks::id.desc()).load::<Task>(&db()).unwrap()
pub fn all(conn: &SqliteConnection) -> Vec<Task> {
all_tasks.order(tasks::id.desc()).load::<Task>(conn).unwrap()
}
pub fn insert(&self) -> bool {
diesel::insert(self).into(tasks::table).execute(&db()).is_ok()
pub fn insert(&self, conn: &SqliteConnection) -> bool {
diesel::insert(self).into(tasks::table).execute(conn).is_ok()
}
pub fn toggle_with_id(id: i32) -> bool {
let task = all_tasks.find(id).get_result::<Task>(&db());
pub fn toggle_with_id(id: i32, conn: &SqliteConnection) -> bool {
let task = all_tasks.find(id).get_result::<Task>(conn);
if task.is_err() {
return false;
}
let new_status = !task.unwrap().completed.unwrap();
let updated_task = diesel::update(all_tasks.find(id));
updated_task.set(task_completed.eq(new_status)).execute(&db()).is_ok()
updated_task.set(task_completed.eq(new_status)).execute(conn).is_ok()
}
pub fn delete_with_id(id: i32) -> bool {
diesel::delete(all_tasks.find(id)).execute(&db()).is_ok()
pub fn delete_with_id(id: i32, conn: &SqliteConnection) -> bool {
diesel::delete(all_tasks.find(id)).execute(conn).is_ok()
}
}