Adjusting to make the database better tested.
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
///
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Legend
|
||||
{
|
||||
/// A link to the adventurer's profile (e.g., personal website, GitHub,
|
||||
@ -20,7 +20,7 @@ pub struct Legend
|
||||
///
|
||||
/// An `Adventurer` contains identifying and descriptive information
|
||||
/// such as their name, handle, profile URL, image, and a short blurb.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Adventurer
|
||||
{
|
||||
/// The full name of the adventurer.
|
||||
@ -34,7 +34,3 @@ pub struct Adventurer
|
||||
#[serde(flatten)]
|
||||
pub legend: Legend
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Adventurer {}
|
||||
|
||||
@ -4,20 +4,20 @@ use std::str::FromStr;
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions};
|
||||
use sqlx::{Error, Result};
|
||||
|
||||
#[cfg(not(feature = "publisher"))]
|
||||
#[cfg(any(not(feature = "publisher"), feature = "tester"))]
|
||||
use sqlx::Row;
|
||||
|
||||
use crate::adventurer::Adventurer;
|
||||
use crate::tale::Tale;
|
||||
use crate::tale::{Story, Tale};
|
||||
|
||||
#[cfg(feature = "publisher")]
|
||||
use crate::converter::Converter;
|
||||
#[cfg(feature = "publisher")]
|
||||
use crate::tavern::Tavern;
|
||||
|
||||
#[cfg(not(feature = "publisher"))]
|
||||
#[cfg(any(not(feature = "publisher"), feature = "tester"))]
|
||||
use crate::tale::Lore;
|
||||
#[cfg(not(feature = "publisher"))]
|
||||
#[cfg(any(not(feature = "publisher"), feature = "tester"))]
|
||||
use crate::adventurer::Legend;
|
||||
|
||||
|
||||
@ -140,13 +140,24 @@ impl Database
|
||||
-> Result<()>
|
||||
{
|
||||
// Convert the tales content from Markdown to HTML.
|
||||
let markdown_content = std::fs::read_to_string(&tale.story)?;
|
||||
let html_content: String = Converter::markdown_to_html(&markdown_content);
|
||||
let html_content: std::borrow::Cow<'_, str> = match &tale.story
|
||||
{
|
||||
Story::Html(story) => { std::borrow::Cow::Borrowed(story) }
|
||||
|
||||
Story::File(path) =>
|
||||
{
|
||||
let markdown = std::fs::read_to_string(path)?;
|
||||
std::borrow::Cow::Owned(Converter::markdown_to_html(&markdown))
|
||||
}
|
||||
};
|
||||
|
||||
// Start a transaction.
|
||||
let mut tx = self.pool.begin().await?;
|
||||
|
||||
// Store the tale.
|
||||
// Pull the HTML content out first so that the str will last long enough.
|
||||
// This get's around the macro lifetime issue.
|
||||
let html_str = html_content.as_ref();
|
||||
sqlx::query!(
|
||||
"INSERT OR REPLACE INTO tales (
|
||||
slug, title, author, summary, publish_date, content
|
||||
@ -156,7 +167,7 @@ impl Database
|
||||
tale.lore.author,
|
||||
tale.lore.summary,
|
||||
tale.lore.publish_date,
|
||||
html_content
|
||||
html_str
|
||||
).execute(&mut *tx) // Pass mutable reference to the transaction
|
||||
.await?;
|
||||
|
||||
@ -263,7 +274,7 @@ impl Database
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "publisher"))]
|
||||
#[cfg(any(not(feature = "publisher"), feature = "tester"))]
|
||||
pub async fn get_tales_summary(&self, categories: &[String])
|
||||
-> Result<Vec<Lore>>
|
||||
{
|
||||
@ -312,7 +323,7 @@ impl Database
|
||||
.unwrap_or_default();
|
||||
|
||||
let date_str: String = row.try_get("publish_date")?;
|
||||
let publish_date = chrono::NaiveDateTime::parse_from_str(&date_str, "%Y-%m-%dT%H:%M:%S")
|
||||
let publish_date = chrono::NaiveDateTime::parse_from_str(&date_str, "%Y-%m-%d %H:%M:%S")
|
||||
.map_err(|e| sqlx::Error::Decode(e.into()))?;
|
||||
|
||||
tales.push(Lore { title: row.try_get("title")?,
|
||||
@ -328,7 +339,7 @@ impl Database
|
||||
Ok(tales)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "publisher"))]
|
||||
#[cfg(any(not(feature = "publisher"), feature = "tester"))]
|
||||
pub async fn get_tale_by_slug(&self, slug: &str) -> Result<Option<Tale>>
|
||||
{
|
||||
let mut tx = self.pool.begin().await?;
|
||||
@ -356,7 +367,7 @@ impl Database
|
||||
.unwrap_or_default();
|
||||
|
||||
let date_str: String = row.try_get("publish_date")?;
|
||||
let publish_date = chrono::NaiveDateTime::parse_from_str(&date_str, "%Y-%m-%dT%H:%M:%S")
|
||||
let publish_date = chrono::NaiveDateTime::parse_from_str(&date_str, "%Y-%m-%d %H:%M:%S")
|
||||
.map_err(|e| Error::Decode(e.into()))?;
|
||||
|
||||
let lore = Lore { title: row.try_get("title")?,
|
||||
@ -367,7 +378,7 @@ impl Database
|
||||
tags };
|
||||
|
||||
Ok(Some(Tale { lore,
|
||||
story: row.try_get("content")? }))
|
||||
story: Story::Html(row.try_get("content")?) }))
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -375,7 +386,7 @@ impl Database
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "publisher"))]
|
||||
#[cfg(any(not(feature = "publisher"), feature = "tester"))]
|
||||
pub async fn get_adventurer(&self, handle: &str)
|
||||
-> Result<Option<Adventurer>>
|
||||
{
|
||||
|
||||
@ -17,5 +17,5 @@ pub use crate::adventurer::{Adventurer, Legend};
|
||||
#[cfg(feature = "database")]
|
||||
pub use crate::database::Database;
|
||||
pub use crate::info::{get_name, get_version};
|
||||
pub use crate::tale::{Lore, Tale};
|
||||
pub use crate::tale::{Story, Lore, Tale};
|
||||
pub use crate::tavern::Tavern;
|
||||
|
||||
@ -1,17 +1,15 @@
|
||||
use chrono::NaiveDateTime;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
|
||||
/// A type alias representing the path to a Markdown file.
|
||||
/// This type is used to point to the location of the content of a `Tale`.
|
||||
#[cfg(feature = "publisher")]
|
||||
pub type Markdown = std::path::PathBuf;
|
||||
|
||||
|
||||
/// A type alias representing the HTML content of the tale.
|
||||
#[cfg(not(feature = "publisher"))]
|
||||
pub type Markdown = String;
|
||||
#[derive(Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub enum Story
|
||||
{
|
||||
File(std::path::PathBuf),
|
||||
Html(String)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -19,7 +17,7 @@ pub type Markdown = String;
|
||||
///
|
||||
/// This includes details such as the title, author, summary, and
|
||||
/// associated tags.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Lore
|
||||
{
|
||||
/// The title of the tale.
|
||||
@ -44,13 +42,14 @@ pub struct Lore
|
||||
|
||||
|
||||
/// Represents a post or story in the application.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Tale
|
||||
{
|
||||
/// Metadata of the post.
|
||||
#[serde(flatten)]
|
||||
pub lore: Lore,
|
||||
|
||||
/// The file path to the Markdown content of the tale.
|
||||
pub story: Markdown
|
||||
/// The story content for this tale..
|
||||
#[serde(flatten)]
|
||||
pub story: Story
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ use crate::tale::Tale;
|
||||
/// A `Tavern` contains a list of all tales (posts) and their respective
|
||||
/// authors. It serves as the central structure for organizing and serializing
|
||||
/// the site's content.
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Tavern
|
||||
{
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user