-
I have the following table: CREATE TABLE users (
name TEXT PRIMARY KEY,
password_hash TEXT
); And the following #[derive(Insertable, Clone, Debug)]
#[diesel(table_name = crate::database::schema::users)]
#[diesel(primary_key(name))]
#[diesel(check_for_backend(diesel::pg::Pg))]
#[diesel(treat_none_as_default_value = false)]
pub struct User {
#[diesel(serialize_as = String)]
pub name: Username,
#[diesel(serialize_as = Option<String>)]
pub password_hash: Option<PasswordHash>,
}
#[derive(Serialize, Deserialize, Debug, AsExpression)]
#[diesel(sql_type = Nullable<Text>)]
pub struct OptionalPasswordHashSerde(Option<String>);
impl From<Option<PasswordHash>> for OptionalPasswordHashSerde {
fn from(value: Option<PasswordHash>) -> Self {
Self(value.map(Into::into))
}
}
impl From<OptionalPasswordHashSerde> for Option<PasswordHash> {
fn from(value: OptionalPasswordHashSerde) -> Self {
value.0.map(Into::into)
}
}
impl<DB: Backend> ToSql<Nullable<Text>, DB> for OptionalPasswordHashSerde {
fn to_sql<'b>(&'b self, out: &mut diesel::serialize::Output<'b, '_, DB>) -> diesel::serialize::Result {
self.0.to_sql(out) // does not work
}
} But creating this custom type requires me to manually implement
How do I easily implement |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 3 replies
-
The following code works for me: use diesel::prelude::*;
table! {
users(name) {
name -> Text,
password_hash -> Nullable<Text>,
}
}
#[derive(Insertable, Clone, Debug)]
#[diesel(table_name = users)]
#[diesel(primary_key(name))]
#[diesel(check_for_backend(diesel::pg::Pg))]
#[diesel(treat_none_as_default_value = false)]
pub struct User {
#[diesel(serialize_as = String)]
pub name: UserName,
#[diesel(serialize_as = Option<String>)]
pub password_hash: PasswordHash,
}
#[derive(Clone, Debug)]
pub struct UserName(String);
impl From<String> for UserName {
fn from(value: String) -> Self {
Self(value)
}
}
impl From<UserName> for String {
fn from(value: UserName) -> Self {
value.0
}
}
#[derive(Clone, Debug)]
pub struct PasswordHash(Option<String>);
impl From<Option<String>> for PasswordHash {
fn from(value: Option<String>) -> Self {
Self(value)
}
}
impl From<PasswordHash> for Option<String> {
fn from(value: PasswordHash) -> Self {
value.0
}
} Essentially you need to make |
Beta Was this translation helpful? Give feedback.
-
I have a similar where I need both the optional and non-optional type. This is a minimum example: use diesel::prelude::*;
mod schema {
diesel::table! {
users (name) {
name -> Text,
password_hash -> Text,
recovery_hash -> Nullable<Text>,
}
}
}
use schema::*;
#[derive(Debug)]
struct Hash(String);
impl From<Hash> for String {
fn from(value: Hash) -> String {
value.0
}
}
impl From<String> for Hash {
fn from(value: String) -> Hash {
Hash(value)
}
}
#[derive(Queryable, Selectable, Insertable, AsChangeset, Debug)]
struct User {
name: String,
#[diesel(serialize_as = String)]
password_hash: Hash,
#[diesel(serialize_as = Option<String>)]
recovery_hash: Option<Hash>,
} There are a bunch of impls on the actual |
Beta Was this translation helpful? Give feedback.
-
I'm working on this pull request #3837 which will probably make your thing
easier to implement. Feel free to contribute to the pull request, by
forking my branch and making a pull request to my fork of the repo.
…On Fri, 24 Nov 2023, 12.34 Till, ***@***.***> wrote:
I have a similar where I need both the optional and non-optional type.
This is a minimum example:
use diesel::prelude::*;
mod schema {
diesel::table! {
users (name) {
name -> Text,
password_hash -> Text,
recovery_hash -> Nullable<Text>,
}
}}use schema::*;
#[derive(Debug)]struct Hash(String);
impl From<Hash> for String {
fn from(value: Hash) -> String {
value.0
}}
impl From<String> for Hash {
fn from(value: String) -> Hash {
Hash(value)
}}
#[derive(Queryable, Selectable, Insertable, AsChangeset, Debug)]struct User {
name: String,
#[diesel(serialize_as = String)]
password_hash: Hash,
#[diesel(serialize_as = Option<String>)]
recovery_hash: Option<Hash>,}
There are a bunch of impls on the actual Hash that I am working with, so
implementing a second struct OptionHash(Option<Hash>) looks like a bunch
of boilerplate to me. Is it the only option?
—
Reply to this email directly, view it on GitHub
<#3835 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AASATXQQB5MR5JV6CFH24VTYGBZ27AVCNFSM6AAAAAA6FLY6KGVHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM3TMNJZGMYTO>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
How would you implement a structure that updates the hash in database? #[derive(AsChangeset)]
#[diesel(table_name = users)]
pub struct UpdateUser {
#[diesel(serialize_as = Option<Option<String>>)]
pub password_hash: Option<PasswordHash>,
} I'm getting an error on this:
I'm not sure about the implementation of the Into trait because from what I understand, I need to turn an |
Beta Was this translation helpful? Give feedback.
The following code works for me: