Skip to content

Commit 668266d

Browse files
hasezoeySamuelMarks
authored andcommitted
refactor(code): move "default_impl" code to "Struct::render"
And add test for it
1 parent b1be2b8 commit 668266d

File tree

8 files changed

+233
-87
lines changed

8 files changed

+233
-87
lines changed

src/code.rs

Lines changed: 31 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ impl<'a> Struct<'a> {
228228
derives_vec.push(derives::PARTIALEQ);
229229
}
230230

231-
/*if !self.config.options.default_impl*/ {
231+
if !self.config.options.default_impl {
232232
derives_vec.push(derives::DEFAULT);
233233
}
234234
}
@@ -299,7 +299,7 @@ impl<'a> Struct<'a> {
299299
.collect::<Vec<String>>()
300300
.join(" ");
301301

302-
let fields = self.fields();
302+
let mut fields = self.fields();
303303

304304
if fields.is_empty() {
305305
self.has_fields = Some(false);
@@ -332,18 +332,18 @@ impl<'a> Struct<'a> {
332332
};
333333

334334
let mut lines = Vec::with_capacity(fields.len());
335-
for mut f in fields.into_iter() {
335+
for f in fields.iter_mut() {
336336
let field_name = &f.name;
337337

338338
if f.base_type == "String" {
339339
f.base_type = match self.ty {
340-
StructType::Read => f.base_type,
340+
StructType::Read => f.base_type.clone(),
341341
StructType::Update => self.opts.get_update_str_type().as_str().to_string(),
342342
StructType::Create => self.opts.get_create_str_type().as_str().to_string(),
343343
}
344344
} else if f.base_type == "Vec<u8>" {
345345
f.base_type = match self.ty {
346-
StructType::Read => f.base_type,
346+
StructType::Read => f.base_type.clone(),
347347
StructType::Update => self.opts.get_update_bytes_type().as_str().to_string(),
348348
StructType::Create => self.opts.get_create_bytes_type().as_str().to_string(),
349349
}
@@ -382,7 +382,7 @@ impl<'a> Struct<'a> {
382382
),
383383
};
384384

385-
let struct_code = formatdoc!(
385+
let mut struct_code = formatdoc!(
386386
r#"
387387
{doccomment}
388388
{tsync_attr}{derive_attr}
@@ -409,6 +409,14 @@ impl<'a> Struct<'a> {
409409
lines = lines.join("\n"),
410410
);
411411

412+
if self.config.options.default_impl {
413+
struct_code.push('\n');
414+
struct_code.push_str(&build_default_impl_fn(
415+
&ty.format(&table.struct_name),
416+
&fields,
417+
));
418+
}
419+
412420
self.has_fields = Some(true);
413421
self.rendered_code = Some(struct_code);
414422
}
@@ -784,51 +792,40 @@ fn default_for_type(typ: &str) -> &'static str {
784792
}
785793
}
786794

787-
struct NameTypNullable<'a> {
788-
name: String,
789-
typ: &'a str,
790-
nullable: bool,
791-
}
792-
793795
/// Generate default (insides of the `impl Default for StructName { fn default() -> Self {} }`)
794-
fn build_default_impl_fn<'a>(
795-
struct_name: &str,
796-
column_name_type_nullable: impl Iterator<Item = NameTypNullable<'a>>,
797-
) -> String {
798-
let fields_to_defaults = column_name_type_nullable
796+
fn build_default_impl_fn<'a>(struct_name: &str, fields: &[StructField]) -> String {
797+
let fields: Vec<String> = fields
798+
.iter()
799799
.map(|name_typ_nullable| {
800800
format!(
801-
" {name}: {typ_default}",
801+
"{name}: {typ_default},",
802802
name = name_typ_nullable.name,
803-
typ_default = if name_typ_nullable.nullable {
803+
typ_default = if name_typ_nullable.is_optional {
804804
"None"
805805
} else {
806-
default_for_type(name_typ_nullable.typ)
806+
default_for_type(&name_typ_nullable.base_type)
807807
}
808808
)
809809
})
810-
.collect::<Vec<String>>()
811-
.join(",\n");
810+
.collect();
812811
formatdoc!(
813-
r#"impl Default for {struct_name} {{
814-
fn default() -> Self {{
815-
Self {{
816-
{fields_to_defaults}
817-
}}
818-
}}
819-
}}"#
812+
r#"
813+
impl Default for {struct_name} {{
814+
fn default() -> Self {{
815+
Self {{
816+
{fields}
817+
}}
818+
}}
819+
}}
820+
"#,
821+
fields = fields.join("\n ")
820822
)
821823
}
822824

823825
/// Generate a full file for a given diesel table
824826
pub fn generate_for_table(table: &ParsedTableMacro, config: &GenerationConfig) -> String {
825827
// early to ensure the table options are set for the current table
826-
let struct_name = &table.struct_name;
827828
let table_options = config.table(&table.name.to_string());
828-
let generated_columns = table_options.get_autogenerated_columns();
829-
let not_generated = |col: &&ParsedColumnMacro| -> bool {
830-
!generated_columns.contains(&col.column_name.as_str())
831-
};
832829

833830
let mut ret_buffer = format!("{FILE_SIGNATURE}\n\n");
834831

@@ -844,51 +841,13 @@ pub fn generate_for_table(table: &ParsedTableMacro, config: &GenerationConfig) -
844841
if create_struct.has_code() {
845842
ret_buffer.push('\n');
846843
ret_buffer.push_str(create_struct.code());
847-
if config.options.default_impl {
848-
ret_buffer.push('\n');
849-
ret_buffer.push_str(
850-
build_default_impl_fn(
851-
&StructType::format(&StructType::Create, &struct_name),
852-
create_struct
853-
.table
854-
.columns
855-
.iter()
856-
.filter(not_generated)
857-
.map(|col| NameTypNullable {
858-
name: col.column_name.to_string(),
859-
typ: col.ty.as_str(),
860-
nullable: col.is_nullable,
861-
}),
862-
)
863-
.as_str(),
864-
);
865-
}
866844
}
867845

868846
let update_struct = Struct::new(StructType::Update, table, config);
869847

870848
if update_struct.has_code() {
871849
ret_buffer.push('\n');
872850
ret_buffer.push_str(update_struct.code());
873-
/*if config.options.default_impl {
874-
ret_buffer.push('\n');
875-
ret_buffer.push_str(
876-
build_default_impl_fn(
877-
&StructType::format(&StructType::Update, &struct_name),
878-
update_struct
879-
.table
880-
.columns
881-
.iter()
882-
.filter(not_generated)
883-
.map(|col| NameTypNullable {
884-
name: col.column_name.to_string(),
885-
typ: col.ty.as_str(),
886-
nullable: col.is_nullable,
887-
}),
888-
)
889-
.as_str(),
890-
);
891-
}*/
892851
}
893852

894853
// third, push functions - if enabled
@@ -897,20 +856,5 @@ pub fn generate_for_table(table: &ParsedTableMacro, config: &GenerationConfig) -
897856
ret_buffer.push_str(build_table_fns(table, config, create_struct, update_struct).as_str());
898857
}
899858

900-
if config.options.default_impl {
901-
ret_buffer.push('\n');
902-
ret_buffer.push_str(
903-
build_default_impl_fn(
904-
&struct_name,
905-
table.columns.iter().map(|col| NameTypNullable {
906-
name: col.name.to_string().to_owned(),
907-
typ: col.ty.as_str(),
908-
nullable: col.is_nullable,
909-
}),
910-
)
911-
.as_str(),
912-
);
913-
}
914-
915859
ret_buffer
916860
}

test/default_impl/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[lib]
2+
path = "lib.rs"
3+
4+
[package]
5+
name = "default_impl"
6+
version = "0.1.0"
7+
edition = "2021"
8+
9+
[dependencies]
10+
diesel = { version = "*", default-features = false, features = [
11+
"sqlite",
12+
"r2d2",
13+
"chrono",
14+
"returning_clauses_for_sqlite_3_35",
15+
] }
16+
r2d2.workspace = true
17+
chrono.workspace = true
18+
serde.workspace = true

test/default_impl/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub mod models;
2+
pub mod schema;
3+
4+
pub mod diesel {
5+
pub use diesel::*;
6+
}

test/default_impl/models/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod todos;
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/* @generated and managed by dsync */
2+
3+
#[allow(unused)]
4+
use crate::diesel::*;
5+
use crate::schema::*;
6+
7+
pub type ConnectionType = diesel::r2d2::PooledConnection<diesel::r2d2::ConnectionManager<diesel::sqlite::SqliteConnection>>;
8+
9+
/// Struct representing a row in table `todos`
10+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, diesel::Queryable, diesel::Selectable, diesel::QueryableByName, PartialEq, diesel::Identifiable)]
11+
#[diesel(table_name=todos, primary_key(id))]
12+
pub struct Todos {
13+
/// Field representing column `id`
14+
pub id: i32,
15+
/// Field representing column `text`
16+
pub text: String,
17+
/// Field representing column `completed`
18+
pub completed: bool,
19+
/// Field representing column `type`
20+
pub type_: String,
21+
/// Field representing column `smallint`
22+
pub smallint: i16,
23+
/// Field representing column `bigint`
24+
pub bigint: i64,
25+
/// Field representing column `created_at`
26+
pub created_at: chrono::NaiveDateTime,
27+
/// Field representing column `updated_at`
28+
pub updated_at: chrono::NaiveDateTime,
29+
}
30+
31+
impl Default for Todos {
32+
fn default() -> Self {
33+
Self {
34+
id: 0,
35+
text: String::new(),
36+
completed: false,
37+
type_: String::new(),
38+
smallint: 0,
39+
bigint: 0,
40+
created_at: Default::default(),
41+
updated_at: Default::default(),
42+
}
43+
}
44+
}
45+
46+
/// Create Struct for a row in table `todos` for [`Todos`]
47+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, diesel::Insertable)]
48+
#[diesel(table_name=todos)]
49+
pub struct CreateTodos {
50+
/// Field representing column `text`
51+
pub text: String,
52+
/// Field representing column `completed`
53+
pub completed: bool,
54+
/// Field representing column `type`
55+
pub type_: String,
56+
/// Field representing column `smallint`
57+
pub smallint: i16,
58+
/// Field representing column `bigint`
59+
pub bigint: i64,
60+
}
61+
62+
impl Default for CreateTodos {
63+
fn default() -> Self {
64+
Self {
65+
text: String::new(),
66+
completed: false,
67+
type_: String::new(),
68+
smallint: 0,
69+
bigint: 0,
70+
}
71+
}
72+
}
73+
74+
/// Update Struct for a row in table `todos` for [`Todos`]
75+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, diesel::AsChangeset, PartialEq)]
76+
#[diesel(table_name=todos)]
77+
pub struct UpdateTodos {
78+
/// Field representing column `text`
79+
pub text: Option<String>,
80+
/// Field representing column `completed`
81+
pub completed: Option<bool>,
82+
/// Field representing column `type`
83+
pub type_: Option<String>,
84+
/// Field representing column `smallint`
85+
pub smallint: Option<i16>,
86+
/// Field representing column `bigint`
87+
pub bigint: Option<i64>,
88+
/// Field representing column `created_at`
89+
pub created_at: Option<chrono::NaiveDateTime>,
90+
/// Field representing column `updated_at`
91+
pub updated_at: Option<chrono::NaiveDateTime>,
92+
}
93+
94+
impl Default for UpdateTodos {
95+
fn default() -> Self {
96+
Self {
97+
text: String::new(),
98+
completed: false,
99+
type_: String::new(),
100+
smallint: 0,
101+
bigint: 0,
102+
created_at: Default::default(),
103+
updated_at: Default::default(),
104+
}
105+
}
106+
}
107+
108+
/// Result of a `.paginate` function
109+
#[derive(Debug, serde::Serialize)]
110+
pub struct PaginationResult<T> {
111+
/// Resulting items that are from the current page
112+
pub items: Vec<T>,
113+
/// The count of total items there are
114+
pub total_items: i64,
115+
/// Current page, 0-based index
116+
pub page: i64,
117+
/// Size of a page
118+
pub page_size: i64,
119+
/// Number of total possible pages, given the `page_size` and `total_items`
120+
pub num_pages: i64,
121+
}
122+
123+
impl Todos {
124+
/// Insert a new row into `todos` with a given [`CreateTodos`]
125+
pub fn create(db: &mut ConnectionType, item: &CreateTodos) -> diesel::QueryResult<Self> {
126+
use crate::schema::todos::dsl::*;
127+
128+
diesel::insert_into(todos).values(item).get_result::<Self>(db)
129+
}
130+
131+
/// Get a row from `todos`, identified by the primary key
132+
pub fn read(db: &mut ConnectionType, param_id: i32) -> diesel::QueryResult<Self> {
133+
use crate::schema::todos::dsl::*;
134+
135+
todos.filter(id.eq(param_id)).first::<Self>(db)
136+
}
137+
138+
/// Update a row in `todos`, identified by the primary key with [`UpdateTodos`]
139+
pub fn update(db: &mut ConnectionType, param_id: i32, item: &UpdateTodos) -> diesel::QueryResult<Self> {
140+
use crate::schema::todos::dsl::*;
141+
142+
diesel::update(todos.filter(id.eq(param_id))).set(item).get_result(db)
143+
}
144+
145+
/// Delete a row in `todos`, identified by the primary key
146+
pub fn delete(db: &mut ConnectionType, param_id: i32) -> diesel::QueryResult<usize> {
147+
use crate::schema::todos::dsl::*;
148+
149+
diesel::delete(todos.filter(id.eq(param_id))).execute(db)
150+
}
151+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub use generated::*;
2+
pub mod generated;

0 commit comments

Comments
 (0)