diff options
-rw-r--r-- | tosin-macros/src/lib.rs | 101 |
1 files changed, 72 insertions, 29 deletions
diff --git a/tosin-macros/src/lib.rs b/tosin-macros/src/lib.rs index 92945ed..df12069 100644 --- a/tosin-macros/src/lib.rs +++ b/tosin-macros/src/lib.rs @@ -207,7 +207,10 @@ fn impl_model(ast: &syn::DeriveInput) -> TokenStream { ); *self = new_self; } else { - todo!("update existing db item"); + diesel::update(self as &Self) + .set(self as &Self) + .execute(connection) + .unwrap(); } } }; @@ -302,37 +305,76 @@ fn impl_model(ast: &syn::DeriveInput) -> TokenStream { } }; + // used for both insertable and aschangeset + let dsl_eq_types: Vec<_> = ast_data + .fields + .iter() + .filter(|field| !is_id(field)) + .map(|field| { + let ident = &field.ident; + let ty = &field.ty; + quote! { + Option<tosin::db::dsl::Eq<#lowercase_name::#ident, &'a #ty>> + } + }) + .collect(); + let dsl_eq_values: Vec<_> = ast_data + .fields + .iter() + .filter(|field| !is_id(field)) + .map(|field| { + let ident = &field.ident; + quote! { + Some(#lowercase_name::#ident.eq(&self.#ident)) + } + }) + .collect(); + let impl_insertable = { - let insertable_types: Vec<_> = ast_data - .fields - .iter() - .filter(|field| !is_id(field)) - .map(|field| { - let ident = &field.ident; - let ty = &field.ty; - quote! { - Option<tosin::db::dsl::Eq<#lowercase_name::#ident, &'insert #ty>> + quote! { + impl<'a> tosin::db::Insertable<#lowercase_name::table> for &'a #name { + type Values = <(#(#dsl_eq_types,)*) as tosin::db::Insertable<#lowercase_name::table>>::Values; + + fn values(self) -> Self::Values { + use diesel::ExpressionMethods; + (#(#dsl_eq_values,)*).values() } - }) - .collect(); - let insertable_values: Vec<_> = ast_data - .fields - .iter() - .filter(|field| !is_id(field)) - .map(|field| { - let ident = &field.ident; - quote! { - Some(#lowercase_name::#ident.eq(&self.#ident)) + } + } + }; + + let impl_identifiable = { + quote! { + impl<'a> tosin::db::Identifiable for &'a #name { + type Id = Id; + fn id(self) -> Id { + // TODO this probably isn't good + self.id.expect("not actually identifiable if you haven't saved yet") } - }) - .collect(); + } + } + }; + + let impl_has_table = { quote! { - impl<'insert> tosin::db::Insertable<#lowercase_name::table> for &'insert #name { - type Values = <(#(#insertable_types,)*) as tosin::db::Insertable<#lowercase_name::table>>::Values; + impl tosin::db::associations::HasTable for #name { + type Table = #lowercase_name::table; + fn table() -> #lowercase_name::table { + #lowercase_name::table + } + } + } + }; - fn values(self) -> Self::Values { + let impl_as_changeset = { + quote! { + impl<'a> tosin::db::query_builder::AsChangeset for &'a #name { + type Target = #lowercase_name::table; + type Changeset = <(#(#dsl_eq_types,)*) as tosin::db::query_builder::AsChangeset>::Changeset; + + fn as_changeset(self) -> Self::Changeset { use diesel::ExpressionMethods; - (#(#insertable_values,)*).values() + (#(#dsl_eq_values,)*).as_changeset() } } } @@ -350,11 +392,12 @@ fn impl_model(ast: &syn::DeriveInput) -> TokenStream { #(#setters)* } - #impl_queryable - #diesel_table - + #impl_queryable #impl_insertable + #impl_identifiable + #impl_has_table + #impl_as_changeset }; gen.into() } |