Read articles from the actual DB
This commit is contained in:
parent
d9c3bf1191
commit
e997c0f952
6 changed files with 85 additions and 41 deletions
2
migrations/20170820204425_add_articles/down.sql
Normal file
2
migrations/20170820204425_add_articles/down.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
DROP TABLE article_revisions;
|
||||
DROP TABLE articles;
|
16
migrations/20170820204425_add_articles/up.sql
Normal file
16
migrations/20170820204425_add_articles/up.sql
Normal 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)
|
||||
);
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
use chrono;
|
||||
|
||||
#[derive(BartDisplay, Debug, Queryable)]
|
||||
#[template="templates/article.html"]
|
||||
pub struct Article {
|
||||
pub id: i32,
|
||||
#[template="templates/article_revision.html"]
|
||||
pub struct ArticleRevision {
|
||||
pub article_id: i32,
|
||||
pub revision: i32,
|
||||
pub created: chrono::NaiveDateTime,
|
||||
|
||||
|
|
82
src/site.rs
82
src/site.rs
|
@ -59,41 +59,55 @@ impl Service for Site {
|
|||
).boxed()
|
||||
} else {
|
||||
assert!(path.starts_with("/"));
|
||||
match self.state.find_article_by_slug(&path[1..]) {
|
||||
Ok(Some(article)) => {
|
||||
futures::finished(
|
||||
Response::new()
|
||||
.with_header(ContentType(TEXT_HTML.clone()))
|
||||
.with_body(Layout {
|
||||
title: &article.title,
|
||||
body: &article
|
||||
}.to_string())
|
||||
.with_status(hyper::StatusCode::Ok)
|
||||
).boxed()
|
||||
},
|
||||
Ok(None) => {
|
||||
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()
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("Error while servicing request {} {}:\n{:#?}", req.method(), req.path(), err);
|
||||
futures::finished(
|
||||
Response::new()
|
||||
.with_header(ContentType(TEXT_HTML.clone()))
|
||||
.with_body(Layout {
|
||||
title: "Internal server error",
|
||||
body: &InternalServerError,
|
||||
}.to_string())
|
||||
.with_status(hyper::StatusCode::InternalServerError)
|
||||
).boxed()
|
||||
let slug = &path[1..];
|
||||
if let Ok(article_id) = slug.parse() {
|
||||
match self.state.get_article_revision_by_id(article_id) {
|
||||
Ok(Some(article)) => {
|
||||
futures::finished(
|
||||
Response::new()
|
||||
.with_header(ContentType(TEXT_HTML.clone()))
|
||||
.with_body(Layout {
|
||||
title: &article.title,
|
||||
body: &article
|
||||
}.to_string())
|
||||
.with_status(hyper::StatusCode::Ok)
|
||||
).boxed()
|
||||
},
|
||||
Ok(None) => {
|
||||
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()
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("Error while servicing request {} {}:\n{:#?}", req.method(), req.path(), err);
|
||||
futures::finished(
|
||||
Response::new()
|
||||
.with_header(ContentType(TEXT_HTML.clone()))
|
||||
.with_body(Layout {
|
||||
title: "Internal server error",
|
||||
body: &InternalServerError,
|
||||
}.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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
18
src/state.rs
18
src/state.rs
|
@ -2,6 +2,7 @@ use std;
|
|||
|
||||
use chrono;
|
||||
use diesel::sqlite::SqliteConnection;
|
||||
use diesel::prelude::*;
|
||||
|
||||
use models;
|
||||
|
||||
|
@ -14,13 +15,24 @@ impl State {
|
|||
State { db_connection }
|
||||
}
|
||||
|
||||
pub fn find_article_by_slug(&self, slug: &str) -> Result<Option<models::Article>, Box<std::error::Error>> {
|
||||
Ok(Some(models::Article {
|
||||
id: 0,
|
||||
pub fn get_article_revision_by_slug(&self, slug: &str) -> Result<Option<models::ArticleRevision>, Box<std::error::Error>> {
|
||||
Ok(Some(models::ArticleRevision {
|
||||
article_id: 0,
|
||||
revision: 0,
|
||||
created: chrono::Local::now().naive_local(),
|
||||
title: slug.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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<p>{{id}}-{{revision}}</p>
|
||||
<p>{{article_id}}-{{revision}}</p>
|
||||
<p>{{created}}</p>
|
||||
|
||||
<h1>{{title}}</h1>
|
Loading…
Reference in a new issue