diff --git a/examples/postgres/mockable-todos/src/main.rs b/examples/postgres/mockable-todos/src/main.rs index 1fb38c5f..204aa2a2 100644 --- a/examples/postgres/mockable-todos/src/main.rs +++ b/examples/postgres/mockable-todos/src/main.rs @@ -1,6 +1,6 @@ use sqlx::postgres::PgPool; use sqlx::Done; -use std::env; +use std::{env, sync::Arc}; use structopt::StructOpt; #[derive(StructOpt)] @@ -19,16 +19,21 @@ enum Command { #[paw::main] async fn main(args: Args) -> anyhow::Result<()> { let pool = PgPool::connect(&env::var("DATABASE_URL")?).await?; + let todo_repo = PostgresTodoRepo::new(pool); + handle_command(args, todo_repo).await +} + +async fn handle_command(args: Args, todo_repo: PostgresTodoRepo) -> anyhow::Result<()> { match args.cmd { Some(Command::Add { description }) => { println!("Adding new todo with description '{}'", &description); - let todo_id = add_todo(&pool, description).await?; + let todo_id = todo_repo.add_todo(description).await?; println!("Added new todo with id {}", todo_id); } Some(Command::Done { id }) => { println!("Marking todo {} as done", id); - if complete_todo(&pool, id).await? { + if todo_repo.complete_todo(id).await? { println!("Todo {} is marked as done", id); } else { println!("Invalid id {}", id); @@ -36,63 +41,75 @@ async fn main(args: Args) -> anyhow::Result<()> { } None => { println!("Printing list of all todos"); - list_todos(&pool).await?; + todo_repo.list_todos().await?; } } Ok(()) } -async fn add_todo(pool: &PgPool, description: String) -> anyhow::Result { - let rec = sqlx::query!( - r#" +struct PostgresTodoRepo { + pg_pool: Arc, +} + +impl PostgresTodoRepo { + fn new(pg_pool: PgPool) -> Self { + Self { + pg_pool: Arc::new(pg_pool), + } + } + + async fn add_todo(&self, description: String) -> anyhow::Result { + let rec = sqlx::query!( + r#" INSERT INTO todos ( description ) VALUES ( $1 ) RETURNING id "#, - description - ) - .fetch_one(pool) - .await?; + description + ) + .fetch_one(&*self.pg_pool) + .await?; - Ok(rec.id) -} + Ok(rec.id) + } -async fn complete_todo(pool: &PgPool, id: i64) -> anyhow::Result { - let rows_affected = sqlx::query!( - r#" + async fn complete_todo(&self, id: i64) -> anyhow::Result { + let rows_affected = sqlx::query!( + r#" UPDATE todos SET done = TRUE WHERE id = $1 "#, - id - ) - .execute(pool) - .await? - .rows_affected(); + id + ) + .execute(&*self.pg_pool) + .await? + .rows_affected(); - Ok(rows_affected > 0) -} + Ok(rows_affected > 0) + } -async fn list_todos(pool: &PgPool) -> anyhow::Result<()> { - let recs = sqlx::query!( - r#" + async fn list_todos(&self) -> anyhow::Result<()> { + let recs = sqlx::query!( + r#" SELECT id, description, done FROM todos ORDER BY id "# - ) - .fetch_all(pool) - .await?; + ) + .fetch_all(&*self.pg_pool) + .await?; - for rec in recs { - println!( - "- [{}] {}: {}", - if rec.done { "x" } else { " " }, - rec.id, - &rec.description, - ); + for rec in recs { + println!( + "- [{}] {}: {}", + if rec.done { "x" } else { " " }, + rec.id, + &rec.description, + ); + } + + Ok(()) } - - Ok(()) }