Make theme optional when updating articles.

This makes sense from an API design perspective
This commit is contained in:
Magnus Hovland Hoff 2018-10-05 13:07:19 +02:00
parent 09c68c5993
commit ccbabb86f8
2 changed files with 33 additions and 20 deletions

View file

@ -46,7 +46,7 @@ struct UpdateArticle {
base_revision: i32, base_revision: i32,
title: String, title: String,
body: String, body: String,
theme: Theme, theme: Option<Theme>,
} }
pub struct ArticleResource { pub struct ArticleResource {

View file

@ -271,7 +271,7 @@ impl<'a> SyncState<'a> {
Ok(RebaseResult::Clean { title: title_a, body: body_a, theme: theme_a }) Ok(RebaseResult::Clean { title: title_a, body: body_a, theme: theme_a })
} }
pub fn update_article(&self, article_id: i32, base_revision: i32, title: String, body: String, author: Option<String>, theme: Theme) pub fn update_article(&self, article_id: i32, base_revision: i32, title: String, body: String, author: Option<String>, theme: Option<Theme>)
-> Result<UpdateResult, Error> -> Result<UpdateResult, Error>
{ {
if title.is_empty() { if title.is_empty() {
@ -281,15 +281,16 @@ impl<'a> SyncState<'a> {
self.db_connection.transaction(|| { self.db_connection.transaction(|| {
use schema::article_revisions; use schema::article_revisions;
let (latest_revision, prev_title, prev_slug) = article_revisions::table let (latest_revision, prev_title, prev_slug, prev_theme) = article_revisions::table
.filter(article_revisions::article_id.eq(article_id)) .filter(article_revisions::article_id.eq(article_id))
.order(article_revisions::revision.desc()) .order(article_revisions::revision.desc())
.select(( .select((
article_revisions::revision, article_revisions::revision,
article_revisions::title, article_revisions::title,
article_revisions::slug, article_revisions::slug,
article_revisions::theme,
)) ))
.first::<(i32, String, String)>(self.db_connection)?; .first::<(i32, String, String, Theme)>(self.db_connection)?;
// TODO: If this is an historic edit repeated, just respond OK // TODO: If this is an historic edit repeated, just respond OK
// This scheme would make POST idempotent. // This scheme would make POST idempotent.
@ -298,6 +299,7 @@ impl<'a> SyncState<'a> {
Err("This edit is based on a future version of the article")?; Err("This edit is based on a future version of the article")?;
} }
let theme = theme.unwrap_or(prev_theme);
let rebase_result = self.rebase_update(article_id, latest_revision, base_revision, title, body, theme)?; let rebase_result = self.rebase_update(article_id, latest_revision, base_revision, title, body, theme)?;
let (title, body, theme) = match rebase_result { let (title, body, theme) = match rebase_result {
@ -477,7 +479,7 @@ impl State {
self.execute(move |state| state.lookup_slug(slug)) self.execute(move |state| state.lookup_slug(slug))
} }
pub fn update_article(&self, article_id: i32, base_revision: i32, title: String, body: String, author: Option<String>, theme: Theme) pub fn update_article(&self, article_id: i32, base_revision: i32, title: String, body: String, author: Option<String>, theme: Option<Theme>)
-> CpuFuture<UpdateResult, Error> -> CpuFuture<UpdateResult, Error>
{ {
self.execute(move |state| state.update_article(article_id, base_revision, title, body, author, theme)) self.execute(move |state| state.update_article(article_id, base_revision, title, body, author, theme))
@ -544,7 +546,7 @@ mod test {
let article = state.create_article(None, "Title".into(), "Body".into(), None, Theme::Cyan).unwrap(); let article = state.create_article(None, "Title".into(), "Body".into(), None, Theme::Cyan).unwrap();
let new_revision = state.update_article(article.article_id, article.revision, article.title.clone(), "New body".into(), None, Theme::BlueGray).unwrap().unwrap(); let new_revision = state.update_article(article.article_id, article.revision, article.title.clone(), "New body".into(), None, Some(Theme::BlueGray)).unwrap().unwrap();
assert_eq!(article.article_id, new_revision.article_id); assert_eq!(article.article_id, new_revision.article_id);
@ -566,8 +568,8 @@ mod test {
let article = state.create_article(None, "Title".into(), "Body".into(), None, Theme::Cyan).unwrap(); let article = state.create_article(None, "Title".into(), "Body".into(), None, Theme::Cyan).unwrap();
let first_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "New body".into(), None, Theme::Blue).unwrap().unwrap(); let first_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "New body".into(), None, Some(Theme::Blue)).unwrap().unwrap();
let second_edit = state.update_article(article.article_id, first_edit.revision, article.title.clone(), "Newer body".into(), None, Theme::Amber).unwrap().unwrap(); let second_edit = state.update_article(article.article_id, first_edit.revision, article.title.clone(), "Newer body".into(), None, Some(Theme::Amber)).unwrap().unwrap();
assert_eq!("Newer body", second_edit.body); assert_eq!("Newer body", second_edit.body);
assert_eq!(Theme::Amber, second_edit.theme); assert_eq!(Theme::Amber, second_edit.theme);
@ -579,8 +581,8 @@ mod test {
let article = state.create_article(None, "Title".into(), "a\nb\nc\n".into(), None, Theme::Cyan).unwrap(); let article = state.create_article(None, "Title".into(), "a\nb\nc\n".into(), None, Theme::Cyan).unwrap();
let first_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nx\nb\nc\n".into(), None, Theme::Blue).unwrap().unwrap(); let first_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nx\nb\nc\n".into(), None, Some(Theme::Blue)).unwrap().unwrap();
let second_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nb\ny\nc\n".into(), None, Theme::Amber).unwrap().unwrap(); let second_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nb\ny\nc\n".into(), None, Some(Theme::Amber)).unwrap().unwrap();
assert!(article.revision < first_edit.revision); assert!(article.revision < first_edit.revision);
assert!(first_edit.revision < second_edit.revision); assert!(first_edit.revision < second_edit.revision);
@ -595,11 +597,11 @@ mod test {
let article = state.create_article(None, "Title".into(), "a\nb\nc\n".into(), None, Theme::Cyan).unwrap(); let article = state.create_article(None, "Title".into(), "a\nb\nc\n".into(), None, Theme::Cyan).unwrap();
let edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nx1\nb\nc\n".into(), None, article.theme).unwrap().unwrap(); let edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nx1\nb\nc\n".into(), None, Some(article.theme)).unwrap().unwrap();
let edit = state.update_article(article.article_id, edit.revision, article.title.clone(), "a\nx1\nx2\nb\nc\n".into(), None, article.theme).unwrap().unwrap(); let edit = state.update_article(article.article_id, edit.revision, article.title.clone(), "a\nx1\nx2\nb\nc\n".into(), None, Some(article.theme)).unwrap().unwrap();
let edit = state.update_article(article.article_id, edit.revision, article.title.clone(), "a\nx1\nx2\nx3\nb\nc\n".into(), None, article.theme).unwrap().unwrap(); let edit = state.update_article(article.article_id, edit.revision, article.title.clone(), "a\nx1\nx2\nx3\nb\nc\n".into(), None, Some(article.theme)).unwrap().unwrap();
let rebase_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nb\ny\nc\n".into(), None, article.theme).unwrap().unwrap(); let rebase_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nb\ny\nc\n".into(), None, Some(article.theme)).unwrap().unwrap();
assert!(article.revision < edit.revision); assert!(article.revision < edit.revision);
assert!(edit.revision < rebase_edit.revision); assert!(edit.revision < rebase_edit.revision);
@ -613,8 +615,8 @@ mod test {
let article = state.create_article(None, "titlle".into(), "".into(), None, Theme::Cyan).unwrap(); let article = state.create_article(None, "titlle".into(), "".into(), None, Theme::Cyan).unwrap();
let first_edit = state.update_article(article.article_id, article.revision, "Titlle".into(), article.body.clone(), None, article.theme).unwrap().unwrap(); let first_edit = state.update_article(article.article_id, article.revision, "Titlle".into(), article.body.clone(), None, Some(article.theme)).unwrap().unwrap();
let second_edit = state.update_article(article.article_id, article.revision, "title".into(), article.body.clone(), None, article.theme).unwrap().unwrap(); let second_edit = state.update_article(article.article_id, article.revision, "title".into(), article.body.clone(), None, Some(article.theme)).unwrap().unwrap();
assert!(article.revision < first_edit.revision); assert!(article.revision < first_edit.revision);
assert!(first_edit.revision < second_edit.revision); assert!(first_edit.revision < second_edit.revision);
@ -628,8 +630,8 @@ mod test {
let article = state.create_article(None, "Title".into(), "a".into(), None, Theme::Cyan).unwrap(); let article = state.create_article(None, "Title".into(), "a".into(), None, Theme::Cyan).unwrap();
let first_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "b".into(), None, Theme::Blue).unwrap().unwrap(); let first_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "b".into(), None, Some(Theme::Blue)).unwrap().unwrap();
let conflict_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "c".into(), None, Theme::Amber).unwrap(); let conflict_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "c".into(), None, Some(Theme::Amber)).unwrap();
match conflict_edit { match conflict_edit {
UpdateResult::Success(..) => panic!("Expected conflict"), UpdateResult::Success(..) => panic!("Expected conflict"),
@ -650,9 +652,20 @@ mod test {
let article = state.create_article(None, "Title".into(), "a\nb\nc\n".into(), None, Theme::Cyan).unwrap(); let article = state.create_article(None, "Title".into(), "a\nb\nc\n".into(), None, Theme::Cyan).unwrap();
let _first_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nx\nb\nc\n".into(), None, Theme::Blue).unwrap().unwrap(); let _first_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nx\nb\nc\n".into(), None, Some(Theme::Blue)).unwrap().unwrap();
let second_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nb\ny\nc\n".into(), None, Theme::Cyan).unwrap().unwrap(); let second_edit = state.update_article(article.article_id, article.revision, article.title.clone(), "a\nb\ny\nc\n".into(), None, Some(Theme::Cyan)).unwrap().unwrap();
assert_eq!(Theme::Blue, second_edit.theme); assert_eq!(Theme::Blue, second_edit.theme);
} }
#[test]
fn update_article_with_no_given_theme_then_theme_unchanged() {
init!(state);
let article = state.create_article(None, "Title".into(), "a\nb\nc\n".into(), None, Theme::Cyan).unwrap();
let edit = state.update_article(article.article_id, article.revision, article.title, article.body, None, None).unwrap().unwrap();
assert_eq!(Theme::Cyan, edit.theme);
}
} }