aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2021-06-30 13:22:31 -0600
committerMelody Horn <melody@boringcactus.com>2021-06-30 13:22:31 -0600
commitbdfdcb98d39d1887b08748e1ea629f0a83f340a4 (patch)
tree90e3318a04c9f383b3bedd0519ba26be933467f0
parent41d2d919ac27e4f9148d84855c1e591c0b100a11 (diff)
downloadtosin-bdfdcb98d39d1887b08748e1ea629f0a83f340a4.tar.gz
tosin-bdfdcb98d39d1887b08748e1ea629f0a83f340a4.zip
impl Insertable for models
-rw-r--r--tosin-macros/src/lib.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/tosin-macros/src/lib.rs b/tosin-macros/src/lib.rs
index 60803ae..ff62f3d 100644
--- a/tosin-macros/src/lib.rs
+++ b/tosin-macros/src/lib.rs
@@ -173,6 +173,30 @@ fn impl_model(ast: &syn::DeriveInput) -> TokenStream {
diesel_columns,
diesel_types,
} = ast_data.fields.iter().map(to_field_spec).collect();
+
+ 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>>
+ }
+ })
+ .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))
+ }
+ })
+ .collect();
let gen = quote! {
impl #name {
pub const META: ::tosin::db::models::ModelMeta = ::tosin::db::models::ModelMeta {
@@ -186,6 +210,19 @@ fn impl_model(ast: &syn::DeriveInput) -> TokenStream {
#(#field_names),*
}
}
+
+ pub fn save_mut(&mut self, connection: &mut tosin::db::backend::Connection) {
+ if self.id.is_none() {
+ // no id yet, so not from db, so insert
+ let new_self = tosin::db::insert_into(#lowercase_name::table)
+ .values(&self)
+ .get_result(connection)
+ .expect("error saving to database"); // TODO propagate error
+ *self = new_self;
+ } else {
+ todo!("update existing db item");
+ }
+ }
}
impl<__DB: tosin::db::diesel_backend::Backend, __ST> tosin::db::Queryable<__ST, __DB> for #name
@@ -204,6 +241,14 @@ fn impl_model(ast: &syn::DeriveInput) -> TokenStream {
#(#diesel_columns,)*
}
}
+
+ impl<'insert> tosin::db::Insertable<#lowercase_name::table> for &'insert #name {
+ type Values = <(#(#insertable_types,)*) as tosin::db::Insertable<#lowercase_name::table>>::Values;
+
+ fn values(self) -> Self::Values {
+ (#(#insertable_values,)*).values()
+ }
+ }
};
gen.into()
}