域名 AXUM.RS 将于 2025 年 10 月到期。我们无意再对其进行续费,如果你有意接续这个域名,请与我们取得联系。
  • AXUM.RS 现仅需人民币 3000 元(大写:叁仟元整。接受适度议价
  • 按照行业规则,AXUM.RS 到期后,大概率会进入长时间的赎回期,该期间内,如果你想拥有该域名,将要付出高额的费用
  • 我们已启用 AXUM.EU.ORG 域名,并将持续运营
  • 仅接受微信或支付宝交易
如果你对 AXUM.RS 有兴趣,请和我们进行联系:

实现TodoItem

经过一番重构,目前我们的 Todo 服务已经基本完善了,现在只差最后一个部分:TodoItem。本章我们就来实现它。

本章代码在06/待办事项分支。

模型定义

/// 待办事项模型
#[derive(PostgresMapper, Serialize)]
#[pg_mapper(table = "todo_item")]
pub struct TodoItem {
    pub id: i32,
    pub title: String,
    pub checked: bool,
    pub list_id: i32,
}

/// 待办事项新ID模型
#[derive(PostgresMapper, Serialize)]
#[pg_mapper(table = "todo_item")]
pub struct TodoItemID {
    pub id: i32,
}

表单定义

#[derive(Deserialize)]
pub struct CreateTodoItem {
    pub title: String,
    pub list_id: i32,
}

数据库操作

pub async fn all(client: &Client, list_id: i32) -> Result<Vec<TodoItem>> {
    let result: Vec<TodoItem> = super::query(
        client,
        "SELECT id,title,checked,list_id FROM todo_item WHERE list_id=$1 ORDER BY id ASC",
        &[&list_id],
    )
    .await?;
    Ok(result)
}

pub async fn find(client: &Client, list_id: i32, item_id: i32) -> Result<TodoItem> {
    let result: TodoItem = super::query_one(
        client,
        "SELECT id,title,checked,list_id FROM todo_item WHERE id=$1 AND list_id=$2",
        &[&item_id, &list_id],
    )
    .await?;
    Ok(result)
}

pub async fn check(client: &Client, list_id: i32, item_id: i32) -> Result<bool> {
    let result = super::execute(
        client,
        "UPDATE todo_item SET checked=true WHERE id=$1 AND list_id=$2 AND checked=false",
        &[&item_id, &list_id],
    )
    .await?;
    Ok(result > 0)
}

pub async fn delete(client: &Client, list_id: i32, item_id: i32) -> Result<bool> {
    let result = super::execute(
        client,
        "DELETE FROM todo_item WHERE id=$1 AND list_id=$2",
        &[&item_id, &list_id],
    )
    .await?;
    Ok(result > 0)
}

pub async fn create(client: &Client, frm: form::CreateTodoItem) -> Result<TodoItemID> {
    let result = query_one(
        client,
        "INSERT INTO todo_item (title, checked, list_id) VALUES ($1,$2,$3) RETURNING id",
        &[&frm.title, &false, &frm.list_id],
    )
    .await?;
    Ok(result)
}

从代码可以看出,都是对父模块相关方法的调用,这里不再赘述。

handler 的定义

同样的,我们创建src/handler/todo_item.rs,并输入以下内容:

pub async fn create(
    Extension(state): Extension<AppState>,
    Json(payload): Json<form::CreateTodoItem>,
) -> HandlerResult<TodoItemID> {
    let handler_name = "todo_item_create";
    let client = get_client(&state, handler_name).await?;
    let result = todo_item::create(&client, payload)
        .await
        .map_err(log_error(handler_name.to_string()))?;
    Ok(Json(Response::ok(result)))
}

pub async fn all(
    Extension(state): Extension<AppState>,
    Path(list_id): Path<i32>,
) -> HandlerResult<Vec<TodoItem>> {
    let handler_name = "todo_item_all";
    let client = get_client(&state, handler_name).await?;
    let result = todo_item::all(&client, list_id)
        .await
        .map_err(log_error(handler_name.to_string()))?;
    Ok(Json(Response::ok(result)))
}

pub async fn find(
    Extension(state): Extension<AppState>,
    Path((list_id, item_id)): Path<(i32, i32)>,
) -> HandlerResult<TodoItem> {
    let handler_name = "todo_item_find";
    let client = get_client(&state, handler_name).await?;
    let result = todo_item::find(&client, list_id, item_id)
        .await
        .map_err(log_error(handler_name.to_string()))?;
    Ok(Json(Response::ok(result)))
}

pub async fn check(
    Extension(state): Extension<AppState>,
    Path((list_id, item_id)): Path<(i32, i32)>,
) -> HandlerResult<bool> {
    let handler_name = "todo_item_check";
    let client = get_client(&state, handler_name).await?;
    let result = todo_item::check(&client, list_id, item_id)
        .await
        .map_err(log_error(handler_name.to_string()))?;
    Ok(Json(Response::ok(result)))
}
pub async fn delete(
    Extension(state): Extension<AppState>,
    Path((list_id, item_id)): Path<(i32, i32)>,
) -> HandlerResult<bool> {
    let handler_name = "todo_item_delete";
    let client = get_client(&state, handler_name).await?;
    let result = todo_item::delete(&client, list_id, item_id)
        .await
        .map_err(log_error(handler_name.to_string()))?;
    Ok(Json(Response::ok(result)))
}

也没什么新知识,都是简单的函数调用。

要查看完整内容,请先登录