Skip to content

Commit

Permalink
feat: combined data repo
Browse files Browse the repository at this point in the history
This seems like the right idea so that I don't have multiple pools being cloned.

Still learning, not attached to the solution but now I get to satisfy  the test
  • Loading branch information
jasonribble committed Sep 30, 2024
1 parent 2a48813 commit b6011e2
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 72 deletions.
13 changes: 13 additions & 0 deletions src/db/connection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use sqlx::SqlitePool;
use std::sync::Arc;
pub struct Connection {
pub sqlite_pool: Arc<SqlitePool>,
}

impl Connection {
pub fn new(pool: SqlitePool) -> Self {
Self {
sqlite_pool: Arc::new(pool),
}
}
}
49 changes: 18 additions & 31 deletions src/db/contact_repo.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
use std::sync::Arc;

use crate::models;
use async_trait::async_trait;
use sqlx::SqlitePool;

use super::connection::Connection;

#[cfg_attr(test, mockall::automock)]
#[async_trait]
pub trait ContactRepo {
async fn create(&self, contact: models::Contact) -> anyhow::Result<i64>;
async fn get_all(&self) -> anyhow::Result<Vec<models::IndexedContact>>;
async fn update(&self, update: models::ContactBuilder) -> anyhow::Result<()>;
async fn get_by_id(&self, id: i64) -> anyhow::Result<models::IndexedContact>;
}

pub struct Connection {
sqlite_pool: Arc<SqlitePool>,
}

impl Connection {
pub fn new(pool: SqlitePool) -> Self {
Self {
sqlite_pool: Arc::new(pool),
}
}
async fn create_contact(&self, contact: models::Contact) -> anyhow::Result<i64>;
async fn get_all_contacts(&self) -> anyhow::Result<Vec<models::IndexedContact>>;
async fn update_contact(&self, update: models::ContactBuilder) -> anyhow::Result<()>;
async fn get_contact_by_id(&self, id: i64) -> anyhow::Result<models::IndexedContact>;
}

#[async_trait]
impl ContactRepo for Connection {
async fn create(&self, contact: models::Contact) -> anyhow::Result<i64> {
async fn create_contact(&self, contact: models::Contact) -> anyhow::Result<i64> {
let query = "INSERT INTO contacts
(first_name, last_name, display_name, email, phone_number)
VALUES (?, ?, ?, ?, ?)";
Expand All @@ -43,7 +30,7 @@ impl ContactRepo for Connection {
Ok(result.last_insert_rowid())
}

async fn get_all(&self) -> anyhow::Result<Vec<models::IndexedContact>> {
async fn get_all_contacts(&self) -> anyhow::Result<Vec<models::IndexedContact>> {
let get_contacts_query =
"SELECT id, first_name, last_name, display_name, email, phone_number
FROM contacts
Expand All @@ -57,7 +44,7 @@ impl ContactRepo for Connection {
Ok(contacts_with_id)
}

async fn update(&self, contact: models::ContactBuilder) -> anyhow::Result<()> {
async fn update_contact(&self, contact: models::ContactBuilder) -> anyhow::Result<()> {
sqlx::query!(
r#"
UPDATE contacts
Expand All @@ -84,7 +71,7 @@ impl ContactRepo for Connection {
Ok(())
}

async fn get_by_id(&self, id: i64) -> anyhow::Result<models::IndexedContact> {
async fn get_contact_by_id(&self, id: i64) -> anyhow::Result<models::IndexedContact> {
let query_get_by_id = "SELECT * FROM contacts WHERE id=$1";

let contact: models::IndexedContact =
Expand All @@ -110,12 +97,12 @@ mod tests {
models::Contact::new("John", "Smith", "[email protected]", "123-456-7890").unwrap();

mock_contact_repo
.expect_create()
.expect_create_contact()
.times(1)
.with(eq(test_contact.clone()))
.returning(|_| Ok(1));

let result = mock_contact_repo.create(test_contact).await;
let result = mock_contact_repo.create_contact(test_contact).await;

let result = result.unwrap();

Expand All @@ -133,11 +120,11 @@ mod tests {
}];

mock_contact_repo
.expect_get_all()
.expect_get_all_contacts()
.times(1)
.return_once(move || Ok(contacts));

let result = mock_contact_repo.get_all().await;
let result = mock_contact_repo.get_all_contacts().await;

assert!(result.is_ok());
}
Expand All @@ -147,7 +134,7 @@ mod tests {
let mut mock_contact_repo = MockContactRepo::new();

mock_contact_repo
.expect_update()
.expect_update_contact()
.times(1)
.return_once(|_| Ok(()));

Expand All @@ -161,7 +148,7 @@ mod tests {
)
.unwrap();

let result = mock_contact_repo.update(edits).await;
let result = mock_contact_repo.update_contact(edits).await;

assert!(result.is_ok());
}
Expand All @@ -177,12 +164,12 @@ mod tests {
};

mock_contact_repo
.expect_get_by_id()
.expect_get_contact_by_id()
.times(1)
.with(eq(contact.id))
.return_once(|_| Ok(contact));

let result = mock_contact_repo.get_by_id(1).await;
let result = mock_contact_repo.get_contact_by_id(1).await;

assert!(result.is_ok());

Expand Down
35 changes: 11 additions & 24 deletions src/db/metadata_repo.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
use std::sync::Arc;

use crate::models;
use async_trait::async_trait;
use chrono::SecondsFormat;
use sqlx::SqlitePool;

use super::Connection;

#[cfg_attr(test, mockall::automock)]
#[async_trait]
pub trait MetadataRepo {
async fn create(&self, metadata: models::Metadata) -> anyhow::Result<i64>;
async fn get_by_id(&self, contact_id: i64) -> anyhow::Result<models::Metadata>;
}

pub struct Connection {
sqlite_pool: Arc<SqlitePool>,
}

impl Connection {
pub fn new(pool: SqlitePool) -> Self {
Self {
sqlite_pool: Arc::new(pool),
}
}
async fn create_metadata(&self, metadata: models::Metadata) -> anyhow::Result<i64>;
async fn get_metadata_by_id(&self, contact_id: i64) -> anyhow::Result<models::Metadata>;
}

#[async_trait]
impl MetadataRepo for Connection {
async fn create(&self, metadata: models::Metadata) -> anyhow::Result<i64> {
async fn create_metadata(&self, metadata: models::Metadata) -> anyhow::Result<i64> {
let query = "INSERT INTO contact_metadata
(contact_id,
starred,
Expand Down Expand Up @@ -74,7 +61,7 @@ impl MetadataRepo for Connection {

Ok(result.last_insert_rowid())
}
async fn get_by_id(&self, contact_id: i64) -> anyhow::Result<models::Metadata> {
async fn get_metadata_by_id(&self, contact_id: i64) -> anyhow::Result<models::Metadata> {
let query_get_by_id = "SELECT * FROM contact_metadata WHERE contact_id=$1";

let metadata: models::Metadata = sqlx::query_as::<_, models::Metadata>(query_get_by_id)
Expand Down Expand Up @@ -125,7 +112,7 @@ mod tests {

let test_metadata = models::Metadata::default();

let result = repo.create(test_metadata.clone()).await.unwrap();
let result = repo.create_metadata(test_metadata.clone()).await.unwrap();
assert!(result > 0);
}

Expand All @@ -136,12 +123,12 @@ mod tests {
let test_metadata = models::Metadata::default();

mock_metadata_repo
.expect_create()
.expect_create_metadata()
.times(1)
.with(eq(test_metadata.clone()))
.returning(|_| Ok(1));

let result = mock_metadata_repo.create(test_metadata).await;
let result = mock_metadata_repo.create_metadata(test_metadata).await;

let result = result.unwrap();

Expand All @@ -161,12 +148,12 @@ mod tests {
let test_metadata_clone = test_metadata.clone();

mock_metadata_repo
.expect_get_by_id()
.expect_get_metadata_by_id()
.times(1)
.with(eq(1))
.returning(move |_| Ok(test_metadata_clone.clone()));

let result = mock_metadata_repo.get_by_id(1).await;
let result = mock_metadata_repo.get_metadata_by_id(1).await;

assert!(result.is_ok());

Expand Down
6 changes: 3 additions & 3 deletions src/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
mod connection;
mod contact_repo;
mod metadata_repo;
#[cfg(test)]
mod tests;

pub use contact_repo::Connection as ContactConnection;
pub use contact_repo::ContactRepo;
pub use connection::Connection;

pub use metadata_repo::Connection as MetadataConnection;
pub use contact_repo::ContactRepo;
pub use metadata_repo::MetadataRepo;
9 changes: 4 additions & 5 deletions src/db/tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use sqlx::{sqlite::SqlitePoolOptions, SqlitePool};

use crate::{
db::{ContactConnection, ContactRepo, MetadataConnection, MetadataRepo},
db::{Connection, ContactRepo, MetadataRepo},
models::{Contact, Metadata},
};

Expand Down Expand Up @@ -50,20 +50,19 @@ async fn setup_test_db() -> SqlitePool {
async fn test_create_contact_get_metadata() {
let pool = setup_test_db().await;

let contact_repo = ContactConnection::new(pool.clone());
let metadata_repo = MetadataConnection::new(pool.clone());
let data_repo = Connection::new(pool);

let example_contact =
Contact::new("Lewis", "Carroll", "[email protected]", "777-777-7777").unwrap();

let result_contact_id = contact_repo.create(example_contact).await;
let result_contact_id = data_repo.create_contact(example_contact).await;
let contact_id = result_contact_id.unwrap();

assert_eq!(contact_id, 1);

let default_metadata = Metadata::default();

let result_expected_metadata = metadata_repo.get_by_id(contact_id).await;
let result_expected_metadata = data_repo.get_metadata_by_id(contact_id).await;
let expected_metadata = result_expected_metadata.unwrap();

assert_eq!(default_metadata, expected_metadata);
Expand Down
25 changes: 16 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod utils;

use clap::Parser;
use commander::{Cli, Commands};
use db::{ContactRepo, ContactConnection};
use db::{Connection, ContactRepo};
use models::{Contact, ContactBuilder};
use sqlx::SqlitePool;

Expand All @@ -18,7 +18,7 @@ async fn main() -> anyhow::Result<()> {

let pool = SqlitePool::connect(&env::var("DATABASE_URL")?).await?;

let contact_repo = ContactConnection::new(pool);
let data_repo = Connection::new(pool);

let cli = Cli::parse();

Expand All @@ -35,25 +35,32 @@ async fn main() -> anyhow::Result<()> {

let contact = contact.unwrap();

let id = contact_repo.create(contact).await?;
let id = data_repo.create_contact(contact).await?;

println!("Successfully saved contact {id}");
}
Commands::Edit(value) => {
let contact = ContactBuilder::new(value.id, value.first_name.clone(), value.last_name.clone(), value.display_name.clone(), value.email.clone(), value.phone_number.clone()).unwrap();


let _ = contact_repo.update(contact).await;
let contact = ContactBuilder::new(
value.id,
value.first_name.clone(),
value.last_name.clone(),
value.display_name.clone(),
value.email.clone(),
value.phone_number.clone(),
)
.unwrap();

let _ = data_repo.update_contact(contact).await;
}
Commands::Show => {
let contacts = contact_repo.get_all().await?;
let contacts = data_repo.get_all_contacts().await?;

println!("{contacts:?}");
}
Commands::Get(value) => {
let id = value.id;

let contact = contact_repo.get_by_id(id).await?;
let contact = data_repo.get_contact_by_id(id).await?;

println!("{contact:?}");
}
Expand Down

0 comments on commit b6011e2

Please sign in to comment.