Skip to content

Commit

Permalink
refactor: Move storage in its own module + rework public API
Browse files Browse the repository at this point in the history
  • Loading branch information
ducdetronquito committed Jan 1, 2024
1 parent b8940cf commit cb17018
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 56 deletions.
53 changes: 53 additions & 0 deletions src/birthday_store.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use anyhow::Result;
use chrono::{NaiveDate, NaiveDateTime};
use rusqlite::Connection;

use crate::Birthday;

pub fn add(name: String, date: String) -> Result<()> {
let db = get_db()?;
let date = NaiveDate::parse_from_str(&date, "%Y-%m-%d")?;
let timestamp = to_timestamp(date);
db.execute(
"INSERT INTO birthdays(name, date_timestamp) VALUES(?1, ?2)",
(name, timestamp),
)?;
Ok(())
}

pub fn get_all() -> Result<Vec<Birthday>> {
let db = get_db()?;
let mut statement = db.prepare("SELECT id, name, date_timestamp FROM birthdays")?;
let birthday_iter = statement.query_map([], |row| {
let id = row.get(0)?;
let name = row.get(1)?;
let timestamp = row.get(2)?;
let date = from_timestamp(timestamp);
Ok(Birthday { id, name, date })
})?;
let birthdays: Result<Vec<Birthday>, rusqlite::Error> = birthday_iter.collect();
Ok(birthdays.unwrap())
}

fn get_db() -> Result<Connection> {
let db = Connection::open("test.db")?;
db.execute(
"CREATE TABLE IF NOT EXISTS birthdays (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
date_timestamp INTEGER NOT NULL
) STRICT",
(),
)?;
Ok(db)
}

fn to_timestamp(date: NaiveDate) -> i64 {
date.and_hms_opt(0, 0, 0).unwrap().timestamp()
}

fn from_timestamp(timestamp: i64) -> NaiveDate {
NaiveDateTime::from_timestamp_opt(timestamp, 0)
.unwrap()
.date()
}
62 changes: 11 additions & 51 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,70 +1,30 @@
mod birthday;
mod birthday_store;
use anyhow::{bail, Result};
pub use birthday::Birthday;
use chrono::{Datelike, NaiveDate, NaiveDateTime};
use rusqlite::Connection;
mod birthday;

fn get_db() -> Result<Connection> {
let db = Connection::open("test.db")?;
db.execute(
"CREATE TABLE IF NOT EXISTS birthdays (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
date_timestamp INTEGER NOT NULL
) STRICT",
(),
)?;
Ok(db)
}

fn to_timestamp(date: NaiveDate) -> i64 {
date.and_hms_opt(0, 0, 0).unwrap().timestamp()
}

fn from_timestamp(timestamp: i64) -> NaiveDate {
NaiveDateTime::from_timestamp_opt(timestamp, 0)
.unwrap()
.date()
}
use chrono::{Datelike, NaiveDate};

pub fn add_birthday(name: String, date: String) -> Result<()> {
let db = get_db()?;
let date = NaiveDate::parse_from_str(&date, "%Y-%m-%d")?;
let timestamp = to_timestamp(date);
db.execute(
"INSERT INTO birthdays(name, date_timestamp) VALUES(?1, ?2)",
(name, timestamp),
)?;
Ok(())
pub fn add(name: String, date: String) -> Result<()> {
birthday_store::add(name, date)
}

pub fn get_all_birthdays() -> Result<Vec<Birthday>> {
let db = get_db()?;
let mut statement = db.prepare("SELECT id, name, date_timestamp FROM birthdays")?;
let birthday_iter = statement.query_map([], |row| {
let id = row.get(0)?;
let name = row.get(1)?;
let timestamp = row.get(2)?;
let date = from_timestamp(timestamp);
Ok(Birthday { id, name, date })
})?;
let birthdays: Result<Vec<Birthday>, rusqlite::Error> = birthday_iter.collect();
Ok(birthdays.unwrap())
pub fn get_all() -> Result<Vec<Birthday>> {
birthday_store::get_all()
}

pub fn get_next_birthday(today: NaiveDate) -> Result<Option<Birthday>> {
let mut birthdays = get_all_birthdays()?;
pub fn get_next(today: NaiveDate) -> Result<Option<Birthday>> {
let mut birthdays = birthday_store::get_all()?;
birthdays.sort_by_key(|birthday| birthday.next(today));
Ok(birthdays.into_iter().next())
}

pub fn search_birthdays(
pub fn search(
name: Option<String>,
year: Option<i32>,
month: Option<u32>,
day: Option<u32>,
) -> Result<Vec<Birthday>> {
let mut birthdays = get_all_birthdays()?;
let mut birthdays = birthday_store::get_all()?;

if let Some(name) = name {
birthdays.retain(|birthday| birthday.name.contains(&name));
Expand Down
10 changes: 5 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ fn main() -> Result<()> {
let cli = Cli::parse();
println!("You ran cli with: {:?}", cli);
match cli.command {
Command::Add { name, date } => birthday::add_birthday(name, date),
Command::Add { name, date } => birthday::add(name, date),
Command::All {} => {
let birthdays = birthday::get_all_birthdays()?;
let birthdays = birthday::get_all()?;
print_birthdays(birthdays);
Ok(())
}
Command::Next {} => {
let today = Utc::now().date_naive();
let maybe_birthday = birthday::get_next_birthday(today)?;
let maybe_birthday = birthday::get_next(today)?;
if let Some(birthday) = maybe_birthday {
print_birthdays(vec![birthday]);
}
Expand All @@ -60,13 +60,13 @@ fn main() -> Result<()> {
month,
day,
} => {
let birthdays = birthday::search_birthdays(name, year, month, day)?;
let birthdays = birthday::search(name, year, month, day)?;
print_birthdays(birthdays);
Ok(())
}
Command::Today {} => {
let today = Utc::now().date_naive();
let birthdays = birthday::search_birthdays(
let birthdays = birthday::search(
None,
Some(today.year()),
Some(today.month()),
Expand Down

0 comments on commit cb17018

Please sign in to comment.