前面三篇我們透過 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,今天就先到這邊我們明天見!