为泛型类型编写Diesel CRUD操作 [英] Writing Diesel CRUD operations for generic types
问题描述
我正在尝试编写一个Rust板条箱,当使用柴油
I am trying to write a Rust crate which removes some boilerplate code from the user when creating simple CRUD operations with Diesel
例如,如果您有这样的柴油机 Insertable
:
For instance, if you have a Diesel Insertable
like this one:
#[derive(Insertable)]
#[table_name = "users"]
pub struct UserCreate<'a> {
pub email: String,
pub hash: &'a [u8],
pub first_name: Option<String>,
pub family_name: Option<String>,
}
我希望板条箱用户只编写 create< UserCreate>(模型,池)
,以将struct字段插入数据库行中.
I want the crate user to just write create<UserCreate>(model, pool)
, to insert the struct fields into a database row.
为此,我编写了以下函数签名(例如,经过简化):
To do so, I've written the following function signature (simplified for example):
fn create<'a, C: 'a>(model: C, pool: DBPool)
where
C: diesel::Identifiable,
&'a C: diesel::Insertable<C::Table>,
{
let conn = pool.get().unwrap();
diesel::insert_into(C::table())
.values(&model)
.execute(&conn);
}
问题在于,编译器抱怨在 .execute(& conn)
处 C
和& C
缺少某些特征范围而且我不太确定如何将它们放在 where
子句中,也许还有一种我不知道的更简单的方法.任何提示都非常欢迎!
The issue is that the compiler complains about some missing trait bounds for C
and &C
at .execute(&conn)
and I am not quite sure how to place them in the where
clause, there may be also a simpler way of doing this which I am not aware of. Any hint is very welcome!
编译器输出:
error[E0277]: the trait bound `<<C as diesel::associations::HasTable>::Table as diesel::QuerySource>::FromClause: diesel::query_builder::QueryFragment<_>` is not satisfied
--> database/src/users/models.rs:46:10
|
46 | .execute(&conn);
| ^^^^^^^ the trait `diesel::query_builder::QueryFragment<_>` is not implemented for `<<C as diesel::associations::HasTable>::Table as diesel::QuerySource>::FromClause`
|
= help: the following implementations were found:
<&'a T as diesel::query_builder::QueryFragment<DB>>
= note: required because of the requirements on the impl of `diesel::query_builder::QueryFragment<_>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
= note: required because of the requirements on the impl of `diesel::query_dsl::load_dsl::ExecuteDsl<_, _>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
error[E0277]: the trait bound `<&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values: diesel::query_builder::QueryFragment<_>` is not satisfied
--> database/src/users/models.rs:46:10
|
46 | .execute(&conn);
| ^^^^^^^ the trait `diesel::query_builder::QueryFragment<_>` is not implemented for `<&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values`
|
= help: the following implementations were found:
<&'a T as diesel::query_builder::QueryFragment<DB>>
= note: required because of the requirements on the impl of `diesel::query_builder::QueryFragment<_>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
= note: required because of the requirements on the impl of `diesel::query_dsl::load_dsl::ExecuteDsl<_, _>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
error[E0277]: the trait bound `<&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values: diesel::insertable::CanInsertInSingleQuery<_>` is not satisfied
--> database/src/users/models.rs:46:10
|
46 | .execute(&conn);
| ^^^^^^^ the trait `diesel::insertable::CanInsertInSingleQuery<_>` is not implemented for `<&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values`
|
= help: the following implementations were found:
<&'a T as diesel::insertable::CanInsertInSingleQuery<DB>>
= note: required because of the requirements on the impl of `diesel::query_builder::QueryFragment<_>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
= note: required because of the requirements on the impl of `diesel::query_dsl::load_dsl::ExecuteDsl<_, _>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
error: aborting due to 3 previous errors
非常感谢!
推荐答案
我终于通过定义以下特征范围来解决了!
I've finally solved by defining the following trait bounds!
fn create<C, T>(model: C, pool: DBPool)
where
T: diesel::associations::HasTable,
<T::Table as diesel::QuerySource>::FromClause:
diesel::query_builder::QueryFragment<diesel::pg::Pg>,
C: diesel::Insertable<T::Table>,
C::Values: diesel::insertable::CanInsertInSingleQuery<diesel::pg::Pg>
+ diesel::query_builder::QueryFragment<diesel::pg::Pg>,
{
let conn = pool.get().unwrap();
diesel::insert_into(T::table())
.values(model)
.execute(&conn);
}
create::<UserCreate, users::table>(user, pool);
基本上,您需要为 Table
和 Insertable
设置一对额外的边界.如果可以直接从 Insertable
获取表,以避免在函数定义中使用其他类型,那将是很好的,但是我可以使用它:)
Basically, you need a pair of extra bounds for the Table
and the Insertable
. It would be nice if it was possible to get the table directly from the Insertable
, to avoid using another type in the function definition, but I can work with that :)
这篇关于为泛型类型编写Diesel CRUD操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!