【问题标题】:Rust Diesel Abstract update functionRust Diesel Abstract 更新函数
【发布时间】:2021-12-24 13:45:58
【问题描述】:

我目前正在尝试实现抽象函数,该函数将为数据库中的任何表更新一些元字段,但遇到了 Identifiable 问题。

我有一个数据库,其中每个表都有元字段:

....
pub updu: Option<Uuid>, // ID of a user who changed it 
pub updt: Option<NaiveDateTime>, //updated with current date/time on every change
pub ver: Option<i32>, //Version increases on every change
.....

我想实现一个对每个实体进行更新的函数。目前我有这个实现:

pub fn update<Model>(
    conn: &PgConnection,
    old_model: Model,
    mut updated_model: Model,
    user_id: Uuid,
) -> Result<Model, diesel::result::Error>
where
    Model: MetaFields + AsChangeset<Target = <Model as HasTable>::Table> + IntoUpdateTarget,
    Update<Model, Model>: LoadQuery<PgConnection, Model>
{
    updated_model.update_fields(user_id);
    Ok(
        diesel::update(old_model)
            .set(updated_model)
            .get_result(conn).unwrap()
    )

当我尝试调用它时,它会显示此错误:

error[E0277]: the trait bound `Marking: Identifiable` is not satisfied
   --> src/service/marking_service.rs:116:24
    |
116 |     web::block(move || common::dao::update(&conn2, real_marking1[0].clone(), marking2_to_update, jwt_token.user_id))
    |                        ^^^^^^^^^^^^^^^^^^^ the trait `Identifiable` is not implemented for `Marking`
    |
    = help: the following implementations were found:
              <&'ident Marking as Identifiable>
    = note: required because of the requirements on the impl of `IntoUpdateTarget` for `Marking`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `testapi` due to previous error

我在本例中尝试更新的实体是:

use chrono::{NaiveDateTime, Utc};
use common::model::MetaFields;
use common::utils::constants::DEL_MARK_AVAILABLE;
use serde::{Deserialize, Serialize};
use serde_json;
use uuid::Uuid;

use crate::schema::marking;

#[derive(
    Clone,
    Serialize,
    Deserialize,
    Debug,
    Queryable,
    Insertable,
    AsChangeset,
    Identifiable,
    QueryableByName,
    Default,
)]
#[primary_key(uuid)]
#[table_name = "marking"]
pub struct Marking {
    pub uuid: Uuid,
    pub updt: Option<NaiveDateTime>,
    pub ver: Option<i32>,
    pub updu: Option<Uuid>,
    pub comment: Option<String>,
    pub status: Option<String>,
}

impl MetaFields for Marking {
    fn update_fields(&mut self, user_id: Uuid) {
        self.updu = Option::from(user_id);
        self.ver = Option::from(self.ver.unwrap() + 1);
        self.updt = Option::from(Utc::now().naive_local());
    }
}

如您所见,为该实体定义了 Identifiable,但由于某种原因更新无法看到它。有人可以建议我在这里缺少什么吗? 更新,架构:

table! {
    marking (uuid) {
        uuid -> Uuid,
        updt -> Nullable<Timestamp>,
        ver -> Nullable<Int4>,
        updu -> Nullable<Uuid>,
        comment -> Nullable<Varchar>,
        status -> Nullable<Varchar>,
    }
}
diesel = { version = "1.4.6", features = ["postgres", "uuid", "chrono", "uuidv07", "serde_json"] }
r2d2 = "0.8"
r2d2-diesel = "1.0.0"
diesel_json = "0.1.0"

【问题讨论】:

    标签: rust rust-diesel


    【解决方案1】:

    您的代码几乎是正确的。错误消息已经提到了这个问题:

    #[derive(Identifiable)] 确实生成了以下 impl:impl&lt;'a&gt; Identifiable for &amp;'a struct {},这意味着 trait 仅用于对 self 的引用。根据您的其他特征设置,您可以尝试以下操作:

    • 将引用传递为old_model common::dao::update
    • 更改common::dao::update 的定义以将引用作为第二个参数。然后,您可以将 Model 的特征边界分开,以便将 IntoUpdateTarget 绑定在 &amp;Model 上。

    (很难猜测哪个会是更好的解决方案,因为您的问题缺少很多重要的上下文。请尝试在未来提供一个完整的最小示例。)

    【讨论】:

    • 感谢您的回复!这几乎是完整的示例,我添加了一些我认为没有必要的细节。我希望这就足够了。如果还有其他有用的信息,请提出建议。
    • @Dmitrii 我不确定在这里还能说什么。这与您的问题中缺少信息无关,而只是#[derive(Identifiable)] 生成了impl&lt;'a&gt; Identifable for &amp;'a YourType {},这意味着它不是针对类型本身实现的,而仅针对类型的引用。这意味着您的代码可能永远不会以这种方式工作,至少在不更改更新函数的情况下不会。
    猜你喜欢
    • 2020-05-03
    • 2020-09-06
    • 2022-07-14
    • 2021-11-24
    • 2022-09-23
    • 2021-03-30
    • 2020-11-22
    • 2021-10-31
    • 2021-01-09
    相关资源
    最近更新 更多