Skip to content

Commit

Permalink
feat: edit a contact with cli
Browse files Browse the repository at this point in the history
- Builder accepts Option<String> so that the update function can ignore empty (None) values
  - may need to add a feature to "delete" a field then...
- use execute when inserting, updating, or deleting (not returning any rows)
  • Loading branch information
jasonribble committed Jul 24, 2024
1 parent 5163dc5 commit dea5aa2
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 28 deletions.
12 changes: 6 additions & 6 deletions src/commander.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,20 @@ pub struct CreateCommand {
#[derive(Args, Debug)]
pub struct EditCommand {
/// ID of contact to edit
id: i64,
pub id: i64,

#[arg(short, long, value_name = "First Name")]
first_name: Option<String>,
pub first_name: Option<String>,

#[arg(short, long, value_name = "Last Name")]
last_name: Option<String>,
pub last_name: Option<String>,

#[arg(short, long, value_name = "Display Name")]
display_name: Option<String>,
pub display_name: Option<String>,

#[arg(short, long)]
email: Option<String>,
pub email: Option<String>,

#[arg(short, long, value_name = "Phone")]
phone_number: Option<String>,
pub phone_number: Option<String>,
}
7 changes: 5 additions & 2 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ impl ContactRepo for PostgresContactRepo {
contact.update.phone_number,
contact.id
)
.fetch_all(&*self.pg_pool)
.execute(&*self.pg_pool)
.await?;

println!("Contact updated");

Ok(())
}

Expand Down Expand Up @@ -151,7 +153,8 @@ mod tests {
.times(1)
.return_once(|_| Ok(()));

let edits = models::ContactBuilder::new(1).set_email("new_email@example.com");
let edits =
models::ContactBuilder::new(1).set_email(Some("new_email@example.com".to_string()));

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

Expand Down
15 changes: 11 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod utils;
use clap::Parser;
use commander::{Cli, Commands};
use db::{ContactRepo, PostgresContactRepo};
use models::Contact;
use models::{Contact, ContactBuilder};
use sqlx::PgPool;

#[tokio::main]
Expand All @@ -35,12 +35,19 @@ async fn main() -> anyhow::Result<()> {

let contact = contact.unwrap();

let _ = contact_repo.save(contact).await?;
let id = contact_repo.save(contact).await?;

println!("Successfully saved contact.");
println!("Successfully saved contact {id}");
}
Commands::Edit(value) => {
println!("This is an edit command {value:?}");
let contact = ContactBuilder::new(value.id)
.set_email(value.email.clone())
.set_first_name(value.first_name.clone())
.set_last_name(value.last_name.clone())
.set_phone_number(value.phone_number.clone())
.set_display_name(value.display_name.clone());

let _ = contact_repo.update(contact).await;
}
}

Expand Down
40 changes: 25 additions & 15 deletions src/models/contact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,34 +54,40 @@ impl Builder {
&& self.update.phone_number.is_none()
}

pub fn set_first_name(mut self, first_name: &str) -> Self {
self.update.first_name = Some(first_name.to_string());
pub fn set_first_name(mut self, first_name: Option<String>) -> Self {
self.update.first_name = first_name;
self
}

pub fn set_last_name(mut self, last_name: &str) -> Self {
self.update.last_name = Some(last_name.to_string());
pub fn set_last_name(mut self, last_name: Option<String>) -> Self {
self.update.last_name = last_name;
self
}

pub fn set_email(mut self, email: &str) -> Self {
pub fn set_email(mut self, email: Option<String>) -> Self {
let email: &str = email.as_deref().unwrap_or("");

if utils::is_not_valid_email(email) {
self.errors.push(AppError::InvalidEmail(email.to_string()));
}

self.update.email = Some(email.to_string());
self
}

pub fn set_display_name(mut self, display_name: &str) -> Self {
self.update.display_name = Some(display_name.to_string());
pub fn set_display_name(mut self, display_name: Option<String>) -> Self {
self.update.display_name = display_name;
self
}

pub fn set_phone_number(mut self, phone_number: &str) -> Self {
pub fn set_phone_number(mut self, phone_number: Option<String>) -> Self {
let phone_number: &str = phone_number.as_deref().unwrap_or("");

if utils::is_not_valid_phone_number(phone_number) {
self.errors
.push(AppError::InvalidPhoneNumber(phone_number.to_string()));
}

self.update.phone_number = Some(phone_number.to_string());
self
}
Expand Down Expand Up @@ -142,8 +148,8 @@ mod tests {
#[test]
fn test_contact_update_builder() {
let edits = Builder::new(1)
.set_display_name("Nickname")
.set_phone_number("123-233-1221")
.set_display_name(Some("Nickname".to_string()))
.set_phone_number(Some("123-233-1221".to_string()))
.build()
.unwrap();

Expand All @@ -158,9 +164,9 @@ mod tests {
#[test]
fn test_contact_update_builder_2() {
let edits = Builder::new(2)
.set_first_name("Mary")
.set_last_name("Smith")
.set_email("new@email.com")
.set_first_name(Some("Mary".to_string()))
.set_last_name(Some("Smith".to_string()))
.set_email(Some("new@email.com".to_string()))
.build()
.unwrap();

Expand Down Expand Up @@ -193,13 +199,17 @@ mod tests {

#[test]
fn test_invalid_email_builder() {
let result = Builder::new(1).set_email("invalid@example").build();
let result = Builder::new(1)
.set_email(Some("invalid@example".to_string()))
.build();
assert!(result.is_err());
}

#[test]
fn test_invalid_builder_phone_number() {
let result = Builder::new(1).set_phone_number("invalid number").build();
let result = Builder::new(1)
.set_phone_number(Some("invalid number".to_string()))
.build();
assert!(result.is_err());
}
}
2 changes: 1 addition & 1 deletion tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod tests {

cmd.assert()
.success()
.stdout(predicates::str::contains("Successfully saved contact."));
.stdout(predicates::str::contains("Successfully saved contact"));
}

#[test]
Expand Down

0 comments on commit dea5aa2

Please sign in to comment.