read, colors and unpublish
This commit is contained in:
parent
2edb979aef
commit
5bf0fcadeb
|
@ -348,6 +348,16 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.8"
|
||||
|
@ -618,6 +628,7 @@ name = "diesel-demo"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"colored",
|
||||
"diesel",
|
||||
"dotenvy",
|
||||
"libpt",
|
||||
|
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
colored = "2.1.0"
|
||||
diesel = { version = "2.2.1", features = ["serde_json", "sqlite", "uuid", "returning_clauses_for_sqlite_3_35"] }
|
||||
dotenvy = "0.15.7"
|
||||
libpt.workspace = true
|
||||
|
|
|
@ -6,6 +6,7 @@ use self::schema::posts::dsl::*;
|
|||
use std::io::Write;
|
||||
use std::{env, io};
|
||||
|
||||
use colored::Colorize;
|
||||
use diesel::prelude::*;
|
||||
use diesel::sqlite::SqliteConnection;
|
||||
|
||||
|
@ -37,7 +38,6 @@ pub fn load_relevant_posts(conn: &mut SqliteConnection) -> anyhow::Result<Vec<mo
|
|||
// characters. Works well for the regular alphabet
|
||||
pub fn print_posts(posts_to_print: &Vec<models::Post>) {
|
||||
if !posts_to_print.is_empty() {
|
||||
info!("{} posts are in the database", posts_to_print.len());
|
||||
println!(
|
||||
"{: <12}| {: <30} | {: <40}[...] | {: <12} | {: <5}",
|
||||
"id", "title", "body (truncated)", "body len", "is published?"
|
||||
|
@ -57,6 +57,7 @@ pub fn print_posts(posts_to_print: &Vec<models::Post>) {
|
|||
post.published
|
||||
);
|
||||
}
|
||||
info!("total: {}", posts_to_print.len());
|
||||
} else {
|
||||
warn!("Tried to display posts, but there are no posts stored in the database");
|
||||
}
|
||||
|
@ -68,7 +69,7 @@ pub fn read_buf_interactive(buf: &mut String) -> anyhow::Result<()> {
|
|||
let stdin = io::stdin();
|
||||
let mut stdout = io::stdout();
|
||||
|
||||
print!("> ");
|
||||
print!("{}", "> ".green().bold());
|
||||
stdout.flush()?;
|
||||
stdin.read_line(buf)?;
|
||||
*buf = buf.trim().to_string();
|
||||
|
|
|
@ -2,11 +2,24 @@ use diesel::SqliteConnection;
|
|||
use diesel_demo::models::{Post, PostDraft};
|
||||
use libpt::log::{self, debug, error, trace, warn};
|
||||
|
||||
const HELP_TEXT: &str = "\
|
||||
help - show this menu\n\
|
||||
exit - exit the application\n\
|
||||
list - list all posts\n\
|
||||
publish [id] - publish the post with the id [id]\n\
|
||||
unpublish [id] - make the post with the id [id] a draft\n\
|
||||
delete [id] - delete the post with the id [id]\n\
|
||||
read [id] - display the post with the id [id]\n\
|
||||
new - create a new post";
|
||||
|
||||
use colored::*;
|
||||
|
||||
use diesel_demo as lib;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let _logger = log::Logger::builder()
|
||||
.max_level(log::Level::DEBUG)
|
||||
.max_level(log::Level::INFO)
|
||||
.display_level(false)
|
||||
.show_time(false)
|
||||
.build();
|
||||
debug!("logger initialized");
|
||||
|
@ -28,38 +41,62 @@ fn repl(conn: &mut SqliteConnection) -> anyhow::Result<()> {
|
|||
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\
|
||||
list - list all posts\n\
|
||||
publish [id] - delete the post with the id [id]\n\
|
||||
delete [id] - delete the post with the id [id]\n\
|
||||
new - create a new post"
|
||||
)
|
||||
println!("{}", HELP_TEXT.bright_blue())
|
||||
} else if buf.starts_with("EXIT") {
|
||||
break;
|
||||
} else if buf.starts_with("UNPUBLISH") {
|
||||
let id: i32 = match get_id(&buf) {
|
||||
Some(i) => i,
|
||||
None => continue,
|
||||
};
|
||||
if let Err(e) = Post::publish(conn, id, false) {
|
||||
if let Some(e) = e.downcast_ref::<diesel::result::Error>() {
|
||||
if matches!(e, diesel::result::Error::NotFound) {
|
||||
warn!("No post with id {id} exists");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
} else if buf.starts_with("PUBLISH") {
|
||||
let id: i32 = match get_id(&buf) {
|
||||
Some(i) => i,
|
||||
None => continue,
|
||||
};
|
||||
if let Err(e) = Post::publish(conn, id){
|
||||
if let Err(e) = Post::publish(conn, id, true) {
|
||||
if let Some(e) = e.downcast_ref::<diesel::result::Error>() {
|
||||
if matches!(e, diesel::result::Error::NotFound) {
|
||||
warn!("No post with id {id} exists");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
} else if buf.starts_with("READ") {
|
||||
let id: i32 = match get_id(&buf) {
|
||||
Some(i) => i,
|
||||
None => continue,
|
||||
};
|
||||
let r = Post::get(conn, id);
|
||||
let post: Post = if let Err(e) = r {
|
||||
if let Some(e) = e.downcast_ref::<diesel::result::Error>() {
|
||||
if matches!(e, diesel::result::Error::NotFound) {
|
||||
warn!("No post with id {id} exists");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
r.unwrap()
|
||||
};
|
||||
println!("{post}");
|
||||
} else if buf.starts_with("DELETE") {
|
||||
let id: i32 = match get_id(&buf) {
|
||||
Some(i) => i,
|
||||
None => continue,
|
||||
};
|
||||
if let Err(e) = Post::delete(conn, id){
|
||||
if let Err(e) = Post::delete(conn, id) {
|
||||
if let Some(e) = e.downcast_ref::<diesel::result::Error>() {
|
||||
if matches!(e, diesel::result::Error::NotFound) {
|
||||
warn!("No post with id {id} exists");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::fmt::Display;
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use diesel::prelude::*;
|
||||
|
@ -22,14 +23,20 @@ pub struct Post {
|
|||
}
|
||||
|
||||
impl Post {
|
||||
pub fn publish(conn: &mut SqliteConnection, id: i32) -> anyhow::Result<()> {
|
||||
pub fn get(conn: &mut SqliteConnection, id: i32) -> anyhow::Result<Post> {
|
||||
use crate::schema::posts::dsl::posts;
|
||||
|
||||
Ok(posts.find(id).select(Post::as_select()).first(conn)?)
|
||||
}
|
||||
|
||||
pub fn publish(conn: &mut SqliteConnection, id: i32, publish: bool) -> anyhow::Result<()> {
|
||||
use crate::schema::posts::dsl::{posts, published};
|
||||
|
||||
let post = diesel::update(posts.find(id))
|
||||
.set(published.eq(true))
|
||||
.set(published.eq(publish))
|
||||
.returning(Post::as_returning())
|
||||
.get_result(conn)?;
|
||||
info!("updated post {}", post.id);
|
||||
info!("updated post {}: publish = {}", post.id, post.published);
|
||||
Ok(())
|
||||
}
|
||||
pub fn delete(conn: &mut SqliteConnection, id: i32) -> anyhow::Result<()> {
|
||||
|
@ -43,6 +50,12 @@ impl Post {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for Post {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "\n{:<60} | published: {:<5}\n{:=^140}\n\n{}", self.title, self.published, "", self.body)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Insertable, Debug)]
|
||||
#[diesel(table_name = crate::schema::posts)]
|
||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))] // optional but improves generated compiler errors
|
||||
|
|
Loading…
Reference in New Issue