前面三篇我們透過 actix 搭建了我們的第一個 Rust web service 並且把 diesel 的教學給完成了,今天我們就要把上一篇做完的 CRUD 套用在 restful api 上面。
首先我們要改寫的是新增這支程式,
extern crate actixweb;
extern crate diesel;
use self::diesel::prelude::*;
use self::actixweb::*;
use self::models::Post;
use std::env::args;
fn main() {
    use actixweb::schema::posts::dsl::{posts, published};
    let id = args().nth(1).expect("publish_post requires a post id")
        .parse::<i32>().expect("Invalid ID");
    let connection = establish_connection();
    let post = diesel::update(posts.find(id))
        .set(published.eq(true))
        .get_result::<Post>(&connection)
        .expect(&format!("Unable to find post {}", id));
    println!("Published post {}", post.title);
}
那麼我們必須先調整一下 module 才能在 web::Json 裡面用這個類型。
#[derive(Serialize, Deserialize, Insertable)]
#[table_name="posts"]
pub struct NewPost {
    pub title: String,
    pub body: String,
}
note: 這邊一開始改的時候遇到不太懂的 lifetime 估計要補一下。
再來我們來調整一下新增 post 的程式,
pub fn create_post<'a>(conn: &PgConnection, data: NewPost) -> Post {
    use schema::posts;
    diesel::insert_into(posts::table)
        .values(&data)
        .get_result(conn)
        .expect("Error saving new post")
}
這邊就是用 diesel 所提供的 insert_into 來寫入資料。
最後我們在主程式新增 post 的 api 介面
extern crate actixweb;
use actix_web::{post};
use self::actixweb::*;
use self::models::{NewPost};
#[post("/post")]
fn create_post_handler(params: web::Json<NewPost>) -> Result<HttpResponse> {
    let connection = establish_connection();
    let result = create_post(&connection, params.0);
    Ok(HttpResponse::Ok().json(result))
}
fn main() {
    ...
    .service(
        web::scope("/api/v1").service(translate).service(create_post_handler)
    )
}
然後試試看送出 post 成功!

完整專案程式看這邊
筆者今天在做的時候不太順利主要是搞不太懂 Rust 是如何在使用像是 extern 或是 pub mod 等觀念花了不少時間才找出問題。
那麼明天會繼續完成我們的 restful CRUD,今天就先到這邊我們明天見!
![]()