a lot of things happened and my id is now null
cargo devel CI / cargo CI (push) Successful in 3m33s Details

This commit is contained in:
Christoph J. Scherr 2024-06-27 09:58:50 +02:00
parent 53b0b36e66
commit 0603c3f460
6 changed files with 148 additions and 11 deletions

View File

@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
anyhow.workspace = true
diesel = { version = "2.2.1", features = ["serde_json", "sqlite", "uuid"] }
diesel = { version = "2.2.1", features = ["serde_json", "sqlite", "uuid", "returning_clauses_for_sqlite_3_35"] }
dotenvy = "0.15.7"
libpt.workspace = true
serde = { workspace = true, features = ["serde_derive"] }

View File

@ -1,13 +1,19 @@
pub mod models;
pub mod schema;
use std::env;
use std::io::Write;
use std::{env, io};
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;
use dotenvy::dotenv;
use libpt::log::error; // load envars from a `.env` file
use libpt::log::{error, info, warn};
use self::models::*;
use self::schema::posts::dsl::*;
use diesel::prelude::*;
pub fn establish_connection() -> anyhow::Result<SqliteConnection> {
dotenv()?;
@ -16,3 +22,38 @@ pub fn establish_connection() -> anyhow::Result<SqliteConnection> {
Ok(SqliteConnection::establish(&database_url)
.inspect_err(|e| error!("Error connecting to {}:\n{e:#?}", database_url))?)
}
pub fn load_posts(conn: &mut SqliteConnection) -> anyhow::Result<Vec<models::Post>> {
Ok(posts
.filter(published.eq(true))
.limit(5)
.select(Post::as_select())
.load(conn)?)
}
pub fn print_posts(posts_to_print: &Vec<Post>) {
if !posts_to_print.is_empty() {
info!("Displaying {} posts", posts_to_print.len());
for post in posts_to_print {
println!("{}", post.title);
println!("-----------\n");
println!("{}", post.body);
}
} else {
warn!("Tried to display posts, but there are no posts stored in the database");
}
}
// NOTE: this can't handle unicode stuff like 春 and I don't really care
pub fn read_buf_interactive(buf: &mut String) -> anyhow::Result<()> {
buf.clear();
let stdin = io::stdin();
let mut stdout = io::stdout();
print!("> ");
stdout.flush()?;
stdin.read_line(buf)?;
*buf = buf.trim().to_string();
Ok(())
}

View File

@ -1,16 +1,53 @@
use libpt::log::{self, debug};
use diesel::SqliteConnection;
use diesel_demo::models::PostDraft;
use libpt::log::{self, debug, info, trace, warn};
use diesel_demo as lib;
fn main() -> anyhow::Result<()> {
let _logger = log::Logger::builder()
.max_level(log::Level::TRACE)
.uptime(true)
.show_time(false)
.build();
debug!("logger initialized");
let conn = lib::establish_connection()?;
let mut conn = lib::establish_connection()?;
debug!("db connection established");
let posts = lib::load_posts(&mut conn)?;
lib::print_posts(&posts);
trace!("entering the repl");
repl(&mut conn)?;
trace!("leaving the repl");
Ok(())
}
fn repl(conn: &mut SqliteConnection) -> anyhow::Result<()> {
let mut buf = String::new();
loop {
lib::read_buf_interactive(&mut buf)?;
buf = buf.to_uppercase();
if buf.starts_with("HELP") {
println!("\
help - show this menu\n\
exit - exit the application\n\
new - create a new post")
}
else if buf.starts_with("EXIT") {
break;
}
else if buf.starts_with("NEW") {
let post = PostDraft::interactive_create()?;
post.post(conn)?;
}
else {
println!("Bad input: try 'help'");
}
}
Ok(())
}

View File

@ -0,0 +1,61 @@
use std::io::{self, Read, Write};
use diesel::prelude::*;
use crate::schema::posts;
#[cfg(not(windows))]
const EOF: &str = "CTRL+D";
#[cfg(windows)]
const EOF: &str = "CTRL+Z";
#[derive(Queryable, Selectable)]
#[diesel(table_name = crate::schema::posts)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))] // optional but improves generated compiler
// errors
pub struct Post {
pub id: i32,
pub title: String,
pub body: String,
pub published: bool,
}
#[derive(Insertable)]
#[diesel(table_name = crate::schema::posts)]
pub struct PostDraft {
pub title: String,
pub body: String,
}
impl PostDraft {
pub fn new<T: ToString>(title: T, body: T) -> Self {
Self {
title: title.to_string(),
body: body.to_string(),
}
}
pub fn post(self, conn: &mut SqliteConnection) -> anyhow::Result<Post> {
Ok(diesel::insert_into(posts::table)
.values(&self)
.returning(Post::as_returning())
.get_result(conn)?)
}
pub fn interactive_create() -> anyhow::Result<Self> {
let mut title = String::new();
let mut body = String::new();
let mut stdin = io::stdin();
print!("Title: ");
io::stdout().flush()?;
stdin.read_line(&mut title)?;
title = title.trim().to_string();
println!("(End with {} when finished) Body:\n", EOF);
stdin.read_to_string(&mut body)?;
body = body.trim().to_string();
Ok(Self::new(&title, &body))
}
}

View File

@ -2,11 +2,9 @@
diesel::table! {
posts (id) {
id -> Int4, // what the hell is an Int4???? I guess it must
// be a 4 byte integer (u32?), no way it would be a nibble.
title -> Varchar,
body -> Text, // What is the difference between Text and Varchar? I know Varchar
// from various DB stuff but idk Text
id -> Integer,
title -> Text,
body -> Text,
published -> Bool,
}
}