Skip to content

Commit 1d5873c

Browse files
committed
Derive AsChangeset also for the plain struct, similar to Insertable
Address Review comments
1 parent a2b45a1 commit 1d5873c

1 file changed

Lines changed: 38 additions & 10 deletions

File tree

diesel_derives/src/as_changeset.rs

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,23 @@ pub fn derive(item: syn::DeriveInput) -> Result<quote::Tokens, Diagnostic> {
3030
.iter()
3131
.filter(|f| !model.primary_key_names.contains(&f.column_name()))
3232
.collect::<Vec<_>>();
33-
let changeset_ty = fields_for_update
33+
let ref_changeset_ty = fields_for_update.iter().map(|field| {
34+
field_changeset_ty(
35+
field,
36+
table_name,
37+
treat_none_as_null,
38+
Some(quote!(&'update)),
39+
)
40+
});
41+
let ref_changeset_expr = fields_for_update
3442
.iter()
35-
.map(|field| field_changeset_ty(field, table_name, treat_none_as_null));
36-
let changeset_expr = fields_for_update
43+
.map(|field| field_changeset_expr(field, table_name, treat_none_as_null, Some(quote!(&))));
44+
let direct_changeset_ty = fields_for_update
3745
.iter()
38-
.map(|field| field_changeset_expr(field, table_name, treat_none_as_null));
46+
.map(|field| field_changeset_ty(field, table_name, treat_none_as_null, None));
47+
let direct_changeset_expr = fields_for_update
48+
.iter()
49+
.map(|field| field_changeset_expr(field, table_name, treat_none_as_null, None));
3950

4051
if fields_for_update.is_empty() {
4152
Span::call_site()
@@ -57,10 +68,21 @@ pub fn derive(item: syn::DeriveInput) -> Result<quote::Tokens, Diagnostic> {
5768
#where_clause
5869
{
5970
type Target = #table_name::table;
60-
type Changeset = <(#(#changeset_ty,)*) as AsChangeset>::Changeset;
71+
type Changeset = <(#(#ref_changeset_ty,)*) as AsChangeset>::Changeset;
72+
73+
fn as_changeset(self) -> Self::Changeset {
74+
(#(#ref_changeset_expr,)*).as_changeset()
75+
}
76+
}
77+
78+
impl #impl_generics AsChangeset for #struct_name #ty_generics
79+
#where_clause
80+
{
81+
type Target = #table_name::table;
82+
type Changeset = <(#(#direct_changeset_ty,)*) as AsChangeset>::Changeset;
6183

6284
fn as_changeset(self) -> Self::Changeset {
63-
(#(#changeset_expr,)*).as_changeset()
85+
(#(#direct_changeset_expr,)*).as_changeset()
6486
}
6587
}
6688
),
@@ -71,27 +93,33 @@ fn field_changeset_ty(
7193
field: &Field,
7294
table_name: syn::Ident,
7395
treat_none_as_null: bool,
96+
lifetime: Option<quote::Tokens>,
7497
) -> syn::Type {
7598
let column_name = field.column_name();
7699
if !treat_none_as_null && is_option_ty(&field.ty) {
77100
let field_ty = inner_of_option_ty(&field.ty);
78-
parse_quote!(std::option::Option<diesel::dsl::Eq<#table_name::#column_name, &'update #field_ty>>)
101+
parse_quote!(std::option::Option<diesel::dsl::Eq<#table_name::#column_name, #lifetime #field_ty>>)
79102
} else {
80103
let field_ty = &field.ty;
81-
parse_quote!(diesel::dsl::Eq<#table_name::#column_name, &'update #field_ty>)
104+
parse_quote!(diesel::dsl::Eq<#table_name::#column_name, #lifetime #field_ty>)
82105
}
83106
}
84107

85108
fn field_changeset_expr(
86109
field: &Field,
87110
table_name: syn::Ident,
88111
treat_none_as_null: bool,
112+
lifetime: Option<quote::Tokens>,
89113
) -> syn::Expr {
90114
let field_access = field.name.access();
91115
let column_name = field.column_name();
92116
if !treat_none_as_null && is_option_ty(&field.ty) {
93-
parse_quote!(self#field_access.as_ref().map(|x| #table_name::#column_name.eq(x)))
117+
if lifetime.is_some() {
118+
parse_quote!(self#field_access.as_ref().map(|x| #table_name::#column_name.eq(x)))
119+
} else {
120+
parse_quote!(self#field_access.map(|x| #table_name::#column_name.eq(x)))
121+
}
94122
} else {
95-
parse_quote!(#table_name::#column_name.eq(&self#field_access))
123+
parse_quote!(#table_name::#column_name.eq(#lifetime self#field_access))
96124
}
97125
}

0 commit comments

Comments
 (0)