From 8c30ef92f652f411679408344031706745346f02 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sat, 14 Apr 2018 16:33:45 +0200 Subject: [PATCH] refactor(db): Store thread body in the posts table This is a simplification over the previous approach. The OP of a thread is just a normal post like any other in this model, which allows some code simplifications (and future query convenience). --- src/db.rs | 31 ++++++++++++++++++++++++++----- src/handlers.rs | 8 ++++++-- src/models.rs | 2 -- src/render.rs | 17 ++++------------- src/schema.rs | 1 - 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/db.rs b/src/db.rs index 0ff716f70..35d7a6b35 100644 --- a/src/db.rs +++ b/src/db.rs @@ -5,7 +5,7 @@ use diesel; use diesel::prelude::*; use diesel::r2d2::{Pool, ConnectionManager}; use models::*; -use errors::Result; +use errors::{ConverseError, Result}; /// The DB actor itself. Several of these will be run in parallel by /// `SyncArbiter`. @@ -62,7 +62,10 @@ impl Handler for DbExecutor { } /// Message used to create a new thread -pub struct CreateThread(pub NewThread); +pub struct CreateThread { + pub new_thread: NewThread, + pub body: String, +} impl Message for CreateThread { type Result = Result; @@ -73,12 +76,30 @@ impl Handler for DbExecutor { fn handle(&mut self, msg: CreateThread, _: &mut Self::Context) -> Self::Result { use schema::threads; + use schema::posts; let conn = self.0.get()?; - Ok(diesel::insert_into(threads::table) - .values(&msg.0) - .get_result(&conn)?) + conn.transaction::(|| { + // First insert the thread structure itself + let thread: Thread = diesel::insert_into(threads::table) + .values(&msg.new_thread) + .get_result(&conn)?; + + // ... then create the first post in the thread. + let new_post = NewPost { + thread_id: thread.id, + body: msg.body, + author_name: msg.new_thread.author_name.clone(), + author_email: msg.new_thread.author_email.clone(), + }; + + diesel::insert_into(posts::table) + .values(&new_post) + .execute(&conn)?; + + Ok(thread) + }) } } diff --git a/src/handlers.rs b/src/handlers.rs index c97e67731..c866f7a14 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -105,12 +105,16 @@ pub fn submit_thread(state: State, let new_thread = NewThread { title: input.0.title, - body: input.0.body, author_name: author.name, author_email: author.email, }; - state.db.send(CreateThread(new_thread)) + let msg = CreateThread { + new_thread, + body: input.0.body, + }; + + state.db.send(msg) .from_err() .and_then(move |res| { let thread = res?; diff --git a/src/models.rs b/src/models.rs index 388dab485..eb3030ccb 100644 --- a/src/models.rs +++ b/src/models.rs @@ -5,7 +5,6 @@ use schema::{threads, posts}; pub struct Thread { pub id: i32, pub title: String, - pub body: String, pub posted: DateTime, pub author_name: String, pub author_email: String, @@ -26,7 +25,6 @@ pub struct Post { #[table_name="threads"] pub struct NewThread { pub title: String, - pub body: String, pub author_name: String, pub author_email: String, } diff --git a/src/render.rs b/src/render.rs index 37f1c4b7f..f47830fa8 100644 --- a/src/render.rs +++ b/src/render.rs @@ -101,24 +101,15 @@ fn md5_hex(input: &[u8]) -> String { } fn prepare_thread(comrak: &ComrakOptions, page: ThreadPage) -> RenderableThreadPage { - let mut posts = vec![RenderablePost { - // Always pin the ID of the first post. - id: 0, - body: markdown_to_html(&page.thread.body, comrak), - posted: page.thread.posted.into(), - author_name: page.thread.author_name, - author_gravatar: md5_hex(page.thread.author_email.as_bytes()), - }]; - - for post in page.posts { - posts.push(RenderablePost { + let posts = page.posts.into_iter().map(|post| { + RenderablePost { id: post.id, body: markdown_to_html(&post.body, comrak), posted: post.posted.into(), author_name: post.author_name, author_gravatar: md5_hex(post.author_email.as_bytes()), - }); - } + } + }).collect(); RenderableThreadPage { posts, diff --git a/src/schema.rs b/src/schema.rs index 4881056c1..d14c89c4c 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -13,7 +13,6 @@ table! { threads (id) { id -> Int4, title -> Varchar, - body -> Text, posted -> Timestamptz, author_name -> Varchar, author_email -> Varchar,