about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@gmail.com>2018-04-14T14·33+0200
committerVincent Ambo <tazjin@gmail.com>2018-04-14T14·33+0200
commit8c30ef92f652f411679408344031706745346f02 (patch)
treef15ab0ebead519c105c03c128ae7f04c4194074b
parenta90d1cc1a41e405ea397b06a3bc1907291c98b65 (diff)
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).
-rw-r--r--src/db.rs31
-rw-r--r--src/handlers.rs8
-rw-r--r--src/models.rs2
-rw-r--r--src/render.rs17
-rw-r--r--src/schema.rs1
5 files changed, 36 insertions, 23 deletions
diff --git a/src/db.rs b/src/db.rs
index 0ff716f708..35d7a6b354 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<GetThread> 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<Thread>;
@@ -73,12 +76,30 @@ impl Handler<CreateThread> 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::<Thread, ConverseError, _>(|| {
+            // 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 c97e677311..c866f7a140 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -105,12 +105,16 @@ pub fn submit_thread(state: State<AppState>,
 
     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 388dab4853..eb3030ccb3 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<Utc>,
     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 37f1c4b7fe..f47830fa84 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 4881056c1c..d14c89c4c7 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,