Read articles from the actual DB

This commit is contained in:
Johannes Hoff 2017-08-20 23:44:52 +02:00
parent d9c3bf1191
commit e997c0f952
6 changed files with 85 additions and 41 deletions

View file

@ -0,0 +1,2 @@
DROP TABLE article_revisions;
DROP TABLE articles;

View file

@ -0,0 +1,16 @@
CREATE TABLE articles (
id INTEGER PRIMARY KEY NOT NULL
);
CREATE TABLE article_revisions (
article_id INTEGER NOT NULL,
revision INTEGER NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
title TEXT NOT NULL,
body TEXT NOT NULL,
PRIMARY KEY (article_id, revision),
FOREIGN KEY (article_id) REFERENCES articles(id)
);

View file

@ -1,9 +1,9 @@
use chrono; use chrono;
#[derive(BartDisplay, Debug, Queryable)] #[derive(BartDisplay, Debug, Queryable)]
#[template="templates/article.html"] #[template="templates/article_revision.html"]
pub struct Article { pub struct ArticleRevision {
pub id: i32, pub article_id: i32,
pub revision: i32, pub revision: i32,
pub created: chrono::NaiveDateTime, pub created: chrono::NaiveDateTime,

View file

@ -59,41 +59,55 @@ impl Service for Site {
).boxed() ).boxed()
} else { } else {
assert!(path.starts_with("/")); assert!(path.starts_with("/"));
match self.state.find_article_by_slug(&path[1..]) { let slug = &path[1..];
Ok(Some(article)) => { if let Ok(article_id) = slug.parse() {
futures::finished( match self.state.get_article_revision_by_id(article_id) {
Response::new() Ok(Some(article)) => {
.with_header(ContentType(TEXT_HTML.clone())) futures::finished(
.with_body(Layout { Response::new()
title: &article.title, .with_header(ContentType(TEXT_HTML.clone()))
body: &article .with_body(Layout {
}.to_string()) title: &article.title,
.with_status(hyper::StatusCode::Ok) body: &article
).boxed() }.to_string())
}, .with_status(hyper::StatusCode::Ok)
Ok(None) => { ).boxed()
futures::finished( },
Response::new() Ok(None) => {
.with_header(ContentType(TEXT_HTML.clone())) futures::finished(
.with_body(Layout { Response::new()
title: "Not found", .with_header(ContentType(TEXT_HTML.clone()))
body: &NotFound, .with_body(Layout {
}.to_string()) title: "Not found",
.with_status(hyper::StatusCode::NotFound) body: &NotFound,
).boxed() }.to_string())
}, .with_status(hyper::StatusCode::NotFound)
Err(err) => { ).boxed()
eprintln!("Error while servicing request {} {}:\n{:#?}", req.method(), req.path(), err); },
futures::finished( Err(err) => {
Response::new() eprintln!("Error while servicing request {} {}:\n{:#?}", req.method(), req.path(), err);
.with_header(ContentType(TEXT_HTML.clone())) futures::finished(
.with_body(Layout { Response::new()
title: "Internal server error", .with_header(ContentType(TEXT_HTML.clone()))
body: &InternalServerError, .with_body(Layout {
}.to_string()) title: "Internal server error",
.with_status(hyper::StatusCode::InternalServerError) body: &InternalServerError,
).boxed() }.to_string())
.with_status(hyper::StatusCode::InternalServerError)
).boxed()
}
} }
} else {
// slugs must be article IDs... for now
futures::finished(
Response::new()
.with_header(ContentType(TEXT_HTML.clone()))
.with_body(Layout {
title: "Not found",
body: &NotFound,
}.to_string())
.with_status(hyper::StatusCode::NotFound)
).boxed()
} }
} }
} }

View file

@ -2,6 +2,7 @@ use std;
use chrono; use chrono;
use diesel::sqlite::SqliteConnection; use diesel::sqlite::SqliteConnection;
use diesel::prelude::*;
use models; use models;
@ -14,13 +15,24 @@ impl State {
State { db_connection } State { db_connection }
} }
pub fn find_article_by_slug(&self, slug: &str) -> Result<Option<models::Article>, Box<std::error::Error>> { pub fn get_article_revision_by_slug(&self, slug: &str) -> Result<Option<models::ArticleRevision>, Box<std::error::Error>> {
Ok(Some(models::Article { Ok(Some(models::ArticleRevision {
id: 0, article_id: 0,
revision: 0, revision: 0,
created: chrono::Local::now().naive_local(), created: chrono::Local::now().naive_local(),
title: slug.to_owned(), title: slug.to_owned(),
body: "Look at me!".to_owned(), body: "Look at me!".to_owned(),
})) }))
} }
pub fn get_article_revision_by_id(&self, article_id: i32) -> Result<Option<models::ArticleRevision>, Box<std::error::Error>> {
use schema::article_revisions;
Ok(article_revisions::table
.filter(article_revisions::article_id.eq(article_id))
.order(article_revisions::revision.desc())
.limit(1)
.load::<models::ArticleRevision>(&self.db_connection)?
.pop())
}
} }

View file

@ -1,4 +1,4 @@
<p>{{id}}-{{revision}}</p> <p>{{article_id}}-{{revision}}</p>
<p>{{created}}</p> <p>{{created}}</p>
<h1>{{title}}</h1> <h1>{{title}}</h1>