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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
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]]
|
[[package]]
|
||||||
name = "console"
|
name = "console"
|
||||||
version = "0.15.8"
|
version = "0.15.8"
|
||||||
|
@ -618,6 +628,7 @@ name = "diesel-demo"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"colored",
|
||||||
"diesel",
|
"diesel",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
"libpt",
|
"libpt",
|
||||||
|
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
|
colored = "2.1.0"
|
||||||
diesel = { version = "2.2.1", features = ["serde_json", "sqlite", "uuid", "returning_clauses_for_sqlite_3_35"] }
|
diesel = { version = "2.2.1", features = ["serde_json", "sqlite", "uuid", "returning_clauses_for_sqlite_3_35"] }
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
libpt.workspace = true
|
libpt.workspace = true
|
||||||
|
|
|
@ -6,6 +6,7 @@ use self::schema::posts::dsl::*;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::{env, io};
|
use std::{env, io};
|
||||||
|
|
||||||
|
use colored::Colorize;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use diesel::sqlite::SqliteConnection;
|
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
|
// characters. Works well for the regular alphabet
|
||||||
pub fn print_posts(posts_to_print: &Vec<models::Post>) {
|
pub fn print_posts(posts_to_print: &Vec<models::Post>) {
|
||||||
if !posts_to_print.is_empty() {
|
if !posts_to_print.is_empty() {
|
||||||
info!("{} posts are in the database", posts_to_print.len());
|
|
||||||
println!(
|
println!(
|
||||||
"{: <12}| {: <30} | {: <40}[...] | {: <12} | {: <5}",
|
"{: <12}| {: <30} | {: <40}[...] | {: <12} | {: <5}",
|
||||||
"id", "title", "body (truncated)", "body len", "is published?"
|
"id", "title", "body (truncated)", "body len", "is published?"
|
||||||
|
@ -57,6 +57,7 @@ pub fn print_posts(posts_to_print: &Vec<models::Post>) {
|
||||||
post.published
|
post.published
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
info!("total: {}", posts_to_print.len());
|
||||||
} else {
|
} else {
|
||||||
warn!("Tried to display posts, but there are no posts stored in the database");
|
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 stdin = io::stdin();
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
|
|
||||||
print!("> ");
|
print!("{}", "> ".green().bold());
|
||||||
stdout.flush()?;
|
stdout.flush()?;
|
||||||
stdin.read_line(buf)?;
|
stdin.read_line(buf)?;
|
||||||
*buf = buf.trim().to_string();
|
*buf = buf.trim().to_string();
|
||||||
|
|
|
@ -2,11 +2,24 @@ use diesel::SqliteConnection;
|
||||||
use diesel_demo::models::{Post, PostDraft};
|
use diesel_demo::models::{Post, PostDraft};
|
||||||
use libpt::log::{self, debug, error, trace, warn};
|
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;
|
use diesel_demo as lib;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let _logger = log::Logger::builder()
|
let _logger = log::Logger::builder()
|
||||||
.max_level(log::Level::DEBUG)
|
.max_level(log::Level::INFO)
|
||||||
|
.display_level(false)
|
||||||
.show_time(false)
|
.show_time(false)
|
||||||
.build();
|
.build();
|
||||||
debug!("logger initialized");
|
debug!("logger initialized");
|
||||||
|
@ -28,29 +41,52 @@ fn repl(conn: &mut SqliteConnection) -> anyhow::Result<()> {
|
||||||
lib::read_buf_interactive(&mut buf)?;
|
lib::read_buf_interactive(&mut buf)?;
|
||||||
buf = buf.to_uppercase();
|
buf = buf.to_uppercase();
|
||||||
if buf.starts_with("HELP") {
|
if buf.starts_with("HELP") {
|
||||||
println!(
|
println!("{}", HELP_TEXT.bright_blue())
|
||||||
"\
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
} else if buf.starts_with("EXIT") {
|
} else if buf.starts_with("EXIT") {
|
||||||
break;
|
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") {
|
} else if buf.starts_with("PUBLISH") {
|
||||||
let id: i32 = match get_id(&buf) {
|
let id: i32 = match get_id(&buf) {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => continue,
|
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 let Some(e) = e.downcast_ref::<diesel::result::Error>() {
|
||||||
if matches!(e, diesel::result::Error::NotFound) {
|
if matches!(e, diesel::result::Error::NotFound) {
|
||||||
warn!("No post with id {id} exists");
|
warn!("No post with id {id} exists");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
r.unwrap()
|
||||||
};
|
};
|
||||||
|
println!("{post}");
|
||||||
} else if buf.starts_with("DELETE") {
|
} else if buf.starts_with("DELETE") {
|
||||||
let id: i32 = match get_id(&buf) {
|
let id: i32 = match get_id(&buf) {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
|
@ -60,6 +96,7 @@ fn repl(conn: &mut SqliteConnection) -> anyhow::Result<()> {
|
||||||
if let Some(e) = e.downcast_ref::<diesel::result::Error>() {
|
if let Some(e) = e.downcast_ref::<diesel::result::Error>() {
|
||||||
if matches!(e, diesel::result::Error::NotFound) {
|
if matches!(e, diesel::result::Error::NotFound) {
|
||||||
warn!("No post with id {id} exists");
|
warn!("No post with id {id} exists");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::fmt::Display;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
@ -22,14 +23,20 @@ pub struct Post {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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};
|
use crate::schema::posts::dsl::{posts, published};
|
||||||
|
|
||||||
let post = diesel::update(posts.find(id))
|
let post = diesel::update(posts.find(id))
|
||||||
.set(published.eq(true))
|
.set(published.eq(publish))
|
||||||
.returning(Post::as_returning())
|
.returning(Post::as_returning())
|
||||||
.get_result(conn)?;
|
.get_result(conn)?;
|
||||||
info!("updated post {}", post.id);
|
info!("updated post {}: publish = {}", post.id, post.published);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn delete(conn: &mut SqliteConnection, id: i32) -> anyhow::Result<()> {
|
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)]
|
#[derive(Insertable, Debug)]
|
||||||
#[diesel(table_name = crate::schema::posts)]
|
#[diesel(table_name = crate::schema::posts)]
|
||||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))] // optional but improves generated compiler errors
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))] // optional but improves generated compiler errors
|
||||||
|
|
Loading…
Reference in New Issue