articles_rs/articles/
service.rsuse chrono::{DateTime, Utc};
use sqlx::postgres::PgPool;
use std::collections::HashMap;
use std::error;
use std::io::ErrorKind;
use uuid::Uuid;
use crate::postgres_repository::PostgresRepository;
use super::{config::DbConfig, Article, ArticleRepository};
pub struct ArticleService {
repo: ArticleRepository,
}
impl std::fmt::Debug for ArticleService {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ArticleService")
.field("repo", &"ArticleRepository")
.finish()
}
}
impl ArticleService {
pub async fn new(config: DbConfig) -> Self {
let url = &config.get_connection_url();
let pool = PgPool::connect(url)
.await
.expect("unable to connect to the database");
let repo = ArticleRepository::new(pool);
ArticleService { repo }
}
pub async fn get_article_by_id(&self, id: Uuid) -> Result<Article, Box<dyn error::Error>> {
match self.repo.find_by_id(id).await {
Ok(Some(article)) => Ok(article),
Ok(None) => Err(Box::new(std::io::Error::new(
ErrorKind::NotFound,
"Article not found",
))),
Err(e) => Err(Box::new(e)),
}
}
pub async fn delete_article(&self, id: Uuid) -> Result<(), Box<dyn error::Error>> {
match self.repo.delete(id).await {
Ok(_) => Ok(()),
Err(e) => Err(Box::new(e)),
}
}
pub async fn list_articles(
&self,
filter: Option<HashMap<String, String>>,
) -> Result<Vec<Article>, Box<dyn error::Error>> {
match self.repo.list(filter).await {
Ok(v) => Ok(v),
Err(e) => Err(Box::new(e)),
}
}
pub async fn create_article(
&self,
title: &str,
slug: &str,
description: &str,
author: &str,
) -> Result<Uuid, Box<dyn error::Error>> {
let article = Article::new(title, slug, description, author);
match self.repo.create(&article).await {
Ok(id) => Ok(id),
Err(e) => Err(Box::new(e)),
}
}
pub async fn update_article(
&self,
id: Uuid,
title: &str,
slug: &str,
description: &str,
author: &str,
status: Option<&str>,
date: Option<DateTime<Utc>>,
contents: &str,
) -> Result<(), Box<dyn error::Error>> {
let mut article = self
.repo
.find_by_id(id)
.await?
.ok_or_else(|| std::io::Error::new(ErrorKind::NotFound, "Article not found"))?;
article.title = title.to_string();
article.slug = slug.to_string();
article.description = description.to_string();
article.author = author.to_string();
article.content = contents.to_string();
if let Some(s) = status {
article.status = s.to_string();
}
if let Some(d) = date {
article.date = d;
}
match self.repo.update(&article).await {
Ok(_) => Ok(()),
Err(e) => Err(Box::new(e)),
}
}
}