Skip to content

Commit f615296

Browse files
committed
commit working version post refactor
1 parent 5a538e8 commit f615296

File tree

5 files changed

+194
-183
lines changed

5 files changed

+194
-183
lines changed

examples/hello_database/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ extern crate diesel as other_diesel;
77
extern crate serde_derive;
88

99
use diesel::{
10-
self, insert_into, prelude::*, result::Error, update, Associations, FromSqlRow, Identifiable,
10+
self, delete, insert_into, prelude::*, result::Error, update, Associations, FromSqlRow, Identifiable,
1111
Insertable, Queryable,
1212
};
1313
use postgres_resource::*;
@@ -16,6 +16,7 @@ use crate::schema::worlds;
1616
mod schema;
1717

1818
#[resource]
19+
#[table = "worlds"]
1920
struct World {
2021
uuid: Uuid,
2122
name: String,

postgres_resource_derive/src/attr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ impl Attrs {
4141
fn parse_attr(attr: &Attribute, expected: &str) -> Result<Option<LitStr>> {
4242
match attr.parse_meta()? {
4343
NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => {
44-
lit_str.parse().map(Some)
44+
Ok(Some(lit_str))
4545
}
4646
_ => {
4747
let error_span = attr.bracket_token.span;
4848
let message = &format!("expected #[{} = \"...\"]", expected);
49-
Err(syn::Error::new(error_span, message))
49+
Err(Error::new(error_span, message))
5050
}
5151
}
5252
}

postgres_resource_derive/src/builder.rs

Lines changed: 104 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{attr::*, IdentExt, camel_to_snake, r#struct::*};
1+
use crate::{attr::*, IdentExt, camel_to_snake, r#struct::*, AsSnake};
22

33
use proc_macro2::Span;
44
use syn::{
@@ -7,6 +7,7 @@ use syn::{
77
token, Attribute, Ident, LitStr,
88
Meta::*,
99
MetaNameValue,
10+
Index,
1011
};
1112

1213
pub struct Input {
@@ -35,12 +36,12 @@ impl<'i, B: Builder<'i>> Builder<'i> for CustomTableMacro<B> {
3536
}
3637
}
3738

38-
pub struct ModelWithId<B>(pub B);
39+
pub struct ModelWithId;
3940

40-
impl<'i, B: Builder<'i>> Builder<'i> for ModelWithId<B> {
41+
impl<'i> Builder<'i> for ModelWithId {
4142
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
4243
let model_name_with_id = input.parsed_struct.ident.append("WithId");
43-
let fields = self.0.build(input)?;
44+
let fields = ModelWithIdFields.build(input)?;
4445

4546
Ok(quote! {
4647
pub struct #model_name_with_id {
@@ -50,9 +51,9 @@ impl<'i, B: Builder<'i>> Builder<'i> for ModelWithId<B> {
5051
}
5152
}
5253

53-
pub struct Fields;
54+
pub struct ModelWithIdFields;
5455

55-
impl<'i> Builder<'i> for Fields {
56+
impl<'i> Builder<'i> for ModelWithIdFields {
5657
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
5758
let mut fields = Vec::new();
5859
fields.push(quote!(pub id: i32));
@@ -72,12 +73,12 @@ impl<'i> Builder<'i> for Fields {
7273
}
7374
}
7475

75-
pub struct Model<B>(pub B);
76+
pub struct Model;
7677

77-
impl<'i, B: Builder<'i>> Builder<'i> for Model<B> {
78+
impl<'i> Builder<'i> for Model {
7879
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
7980
let model_name = &input.parsed_struct.ident;
80-
let fields = self.0.build(input)?;
81+
let fields = ModelFields.build(input)?;
8182

8283
Ok(quote! {
8384
pub struct #model_name {
@@ -87,9 +88,9 @@ impl<'i, B: Builder<'i>> Builder<'i> for Model<B> {
8788
}
8889
}
8990

90-
pub struct InnerFields;
91+
pub struct ModelFields;
9192

92-
impl<'i> Builder<'i> for InnerFields {
93+
impl<'i> Builder<'i> for ModelFields {
9394
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
9495
let mut fields = Vec::new();
9596
input.parsed_struct.fields.iter().for_each(|field| {
@@ -104,3 +105,95 @@ impl<'i> Builder<'i> for InnerFields {
104105
}
105106
}
106107

108+
pub struct Table;
109+
110+
impl<'i> Builder<'i> for Table {
111+
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
112+
let model = input.parsed_struct.as_snake_plural();
113+
Ok(quote!(crate::schema::#model))
114+
}
115+
}
116+
117+
pub struct QueryableRow;
118+
119+
impl<'i> Builder<'i> for QueryableRow {
120+
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
121+
let mut fields = Vec::new();
122+
fields.push(quote!(i32));
123+
124+
input.parsed_struct.fields.iter().for_each(|field| {
125+
let ty = field.ty();
126+
fields.push(quote!(#ty));
127+
});
128+
129+
Ok(quote!(type Row = (#(#fields,)*);))
130+
}
131+
}
132+
133+
pub struct QueryableFields;
134+
135+
impl<'i> Builder<'i> for QueryableFields {
136+
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
137+
let mut fields = Vec::new();
138+
let mut inner_fields = Vec::new();
139+
140+
let model_name = input.parsed_struct.inner_model_name();
141+
142+
let mut index = 0;
143+
144+
// Push id
145+
let idx = Index::from(index);
146+
fields.push(quote!(id: row.#idx));
147+
148+
input.parsed_struct.fields.iter().enumerate().for_each(|(i, field)| {
149+
let field_name = &field.name;
150+
if !field.fk() {
151+
index = i + 1;
152+
let idx = Index::from(index);
153+
inner_fields.push(quote!(#field_name: row.#idx));
154+
}
155+
});
156+
157+
let generated_inner_fields = quote!({ #(#inner_fields,)* });
158+
159+
// Push inner fields
160+
fields.push(quote!(inner: #model_name #generated_inner_fields));
161+
162+
// Push remaining fields
163+
input.parsed_struct.fields.iter().for_each(|field| {
164+
if field.fk() {
165+
index = index + 1;
166+
let name = &field.name;
167+
let idx = Index::from(index);
168+
fields.push(quote!(#name: row.#idx));
169+
}
170+
});
171+
172+
Ok(quote!(#(#fields,)*))
173+
}
174+
}
175+
176+
pub struct Queryable;
177+
178+
impl<'i> Builder<'i> for Queryable {
179+
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
180+
let table = input.parsed_struct.as_snake_plural();
181+
let fields = QueryableFields.build(input)?;
182+
let row = QueryableRow.build(input)?;
183+
184+
let model_with_id = input.parsed_struct.model_name();
185+
186+
Ok(quote! {
187+
impl diesel::Queryable<#table::SqlType, diesel::pg::Pg> for #model_with_id {
188+
#row
189+
fn build(row: Self::Row) -> Self {
190+
#model_with_id {
191+
#fields
192+
}
193+
}
194+
}
195+
})
196+
}
197+
}
198+
199+

0 commit comments

Comments
 (0)