Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scaffold controller tiny_int type not match #1219

Closed
qingmo opened this issue Jan 26, 2025 · 5 comments
Closed

scaffold controller tiny_int type not match #1219

qingmo opened this issue Jan 26, 2025 · 5 comments

Comments

@qingmo
Copy link

qingmo commented Jan 26, 2025

Description

tiny_int type not match with scaffold's controller result.

To Reproduce

loco new

✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · Saas App with client side rendering
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)

cd myapp

cargo loco generate scaffold demo_tiny name:string count:int is_enabled:tiny_int --api

cargo build

Compiling myapp v0.1.0 (/Users/chaos/rustworkspace/myapp)
error[E0308]: mismatched types
--> src/controllers/demo_tiny.rs:21:29
|
21 | item.is_enabled = Set(self.is_enabled.clone());
| --- ^^^^^^^^^^^^^^^^^^^^^^^ expected Option<i8>, found Option<i16>
| |
| arguments to this function are incorrect

Expected Behavior
./myapp/src/controllers/demo_tiny.rs#Params field is_enabled should be match with ./myapp/src/models/_entities/demo_tinies.rs Model field is_enabled type

build pass

Environment:
macos
rust 1.86.0-nightly

Additional Context

qingmo pushed a commit to qingmo/loco that referenced this issue Jan 26, 2025
@qingmo qingmo mentioned this issue Jan 26, 2025
@qingmo
Copy link
Author

qingmo commented Jan 26, 2025

i have add pr:#1220
Please review it

@kaplanelad
Copy link
Contributor

Thank you for opening this issue and fixing the PR! However, we’ve decided to remove support for tiny_* due to differences in seam types between PostgreSQL and SQLite:

  • PostgreSQL: i16
  • SQLite: i8

Let us know if you have any further questions or concerns.

@qingmo
Copy link
Author

qingmo commented Jan 26, 2025

Thank you for opening this issue and fixing the PR! However, we’ve decided to remove support for tiny_* due to differences in seam types between PostgreSQL and SQLite:

  • PostgreSQL: i16
  • SQLite: i8

Let us know if you have any further questions or concerns.

i have three ways to solve this problem.

  1. add a pub custom_type_mapping: Option to src/config.rs, let developer can contol custom mapping definination.
  2. during loco new processing, prepare two or more mapping.json(sqlite_mapping.json, pg_mappings.json), according to user's database choice, rename relate one to mapping.json.(i don't test it yet)
  3. combine both 1 and 2(lol😂).

i have finished 1st solution. it does work.
$ cd myapp
$ mkdir templates
$ cp /Users/chaos/rustworkspace/loco/loco-gen/src/mappings.json templates/
$ cat config/development.yaml

custom_type_mapping: /Users/chaos/rustworkspace/myapp/templates/mappings.json
diff --git a/loco-gen/src/lib.rs b/loco-gen/src/lib.rs
index 676b4c8..d668a6f 100644
--- a/loco-gen/src/lib.rs
+++ b/loco-gen/src/lib.rs
@@ -118,10 +118,11 @@ impl Mappings {
 
 static MAPPINGS: OnceLock<Mappings> = OnceLock::new();
 
-fn get_mappings() -> &'static Mappings {
+fn get_mappings(custom_type_mapping: Option<String>) -> &'static Mappings {
     MAPPINGS.get_or_init(|| {
-        let json_data = include_str!("./mappings.json");
-        serde_json::from_str(json_data).expect("JSON was not well-formatted")
+        let mapping_path = custom_type_mapping.unwrap_or("./mappings.json".to_owned());
+        let json_data = fs::read_to_string(mapping_path).expect("Failed to read file");
+        serde_json::from_str(json_data.as_str()).expect("JSON was not well-formatted")
     })
 }
 
@@ -223,7 +224,7 @@ pub struct AppInfo {
 /// # Errors
 ///
 /// This function will return an error if it fails
-pub fn generate(rrgen: &RRgen, component: Component, appinfo: &AppInfo) -> Result<GenerateResults> {
+pub fn generate(rrgen: &RRgen, component: Component, appinfo: &AppInfo, custom_type_mapping: Option<String>) -> Result<GenerateResults> {
     /*
     (1)
     XXX: remove hooks generic from child generator, materialize it here and pass it
@@ -234,15 +235,15 @@ pub fn generate(rrgen: &RRgen, component: Component, appinfo: &AppInfo) -> Resul
     let get_result = match component {
         #[cfg(feature = "with-db")]
         Component::Model { name, link, fields } => {
-            model::generate(rrgen, &name, link, &fields, appinfo)?
+            model::generate(rrgen, &name, link, &fields, appinfo, custom_type_mapping)?
         }
         #[cfg(feature = "with-db")]
         Component::Scaffold { name, fields, kind } => {
-            scaffold::generate(rrgen, &name, &fields, &kind, appinfo)?
+            scaffold::generate(rrgen, &name, &fields, &kind, appinfo, custom_type_mapping)?
         }
         #[cfg(feature = "with-db")]
         Component::Migration { name, fields } => {
-            migration::generate(rrgen, &name, &fields, appinfo)?
+            migration::generate(rrgen, &name, &fields, appinfo, custom_type_mapping)?
         }
         Component::Controller {
             name,
diff --git a/loco-gen/src/migration.rs b/loco-gen/src/migration.rs
index 92c000d..af12ad8 100644
--- a/loco-gen/src/migration.rs
+++ b/loco-gen/src/migration.rs
@@ -18,6 +18,7 @@ pub fn generate(
     name: &str,
     fields: &[(String, String)],
     appinfo: &AppInfo,
+    custom_type_mapping: Option<String>,
 ) -> Result<GenerateResults> {
     let pkg_name: &str = &appinfo.app_name;
     let ts = Utc::now();
@@ -26,22 +27,22 @@ pub fn generate(
     match res {
         // NOTE: re-uses the 'new model' migration template!
         infer::MigrationType::CreateTable { table } => {
-            let (columns, references) = get_columns_and_references(fields)?;
+            let (columns, references) = get_columns_and_references(fields, custom_type_mapping)?;
             let vars = json!({"name": table, "ts": ts, "pkg_name": pkg_name, "is_link": false, "columns": columns, "references": references});
             render_template(rrgen, Path::new("model/model.t"), &vars)
         }
         infer::MigrationType::AddColumns { table } => {
-            let (columns, references) = get_columns_and_references(fields)?;
+            let (columns, references) = get_columns_and_references(fields, custom_type_mapping)?;
             let vars = json!({"name": name, "table": table, "ts": ts, "pkg_name": pkg_name, "is_link": false, "columns": columns, "references": references});
             render_template(rrgen, Path::new("migration/add_columns.t"), &vars)
         }
         infer::MigrationType::RemoveColumns { table } => {
-            let (columns, _references) = get_columns_and_references(fields)?;
+            let (columns, _references) = get_columns_and_references(fields, custom_type_mapping)?;
             let vars = json!({"name": name, "table": table, "ts": ts, "pkg_name": pkg_name, "columns": columns});
             render_template(rrgen, Path::new("migration/remove_columns.t"), &vars)
         }
         infer::MigrationType::AddReference { table } => {
-            let (columns, references) = get_columns_and_references(fields)?;
+            let (columns, references) = get_columns_and_references(fields, custom_type_mapping)?;
             let vars = json!({"name": name, "table": table, "ts": ts, "pkg_name": pkg_name, "columns": columns, "references": references});
             render_template(rrgen, Path::new("migration/add_references.t"), &vars)
         }
@@ -52,7 +53,7 @@ pub fn generate(
             let (columns, references) = get_columns_and_references(&[
                 (table_a, "references".to_string()),
                 (table_b, "references".to_string()),
-            ])?;
+            ], custom_type_mapping)?;
             let vars = json!({"name": name, "table": table, "ts": ts, "pkg_name": pkg_name, "columns": columns, "references": references});
             render_template(rrgen, Path::new("migration/join_table.t"), &vars)
         }
diff --git a/loco-gen/src/model.rs b/loco-gen/src/model.rs
index ec812c8..7fcbf66 100644
--- a/loco-gen/src/model.rs
+++ b/loco-gen/src/model.rs
@@ -21,6 +21,7 @@ pub const IGNORE_FIELDS: &[&str] = &["created_at", "updated_at", "create_at", "u
 #[allow(clippy::type_complexity)]
 pub fn get_columns_and_references(
     fields: &[(String, String)],
+    custom_type_mapping: Option<String>,
 ) -> Result<(Vec<(String, String)>, Vec<(String, String)>)> {
     let mut columns = Vec::new();
     let mut references = Vec::new();
@@ -42,7 +43,7 @@ pub fn get_columns_and_references(
                 references.push((fname.to_string(), refname.clone()));
             }
             crate::infer::FieldType::Type(ftype) => {
-                let mappings = get_mappings();
+                let mappings = get_mappings(custom_type_mapping.clone());
                 let col_type = mappings.col_type_field(ftype.as_str()).ok_or_else(|| {
                     Error::Message(format!(
                         "type: `{}` not found. try any of: {:?}",
@@ -53,7 +54,7 @@ pub fn get_columns_and_references(
                 columns.push((fname.to_string(), col_type.to_string()));
             }
             crate::infer::FieldType::TypeWithParameters(ftype, params) => {
-                let mappings = get_mappings();
+                let mappings = get_mappings(custom_type_mapping.clone());
                 let col_type = mappings.col_type_field(ftype.as_str()).ok_or_else(|| {
                     Error::Message(format!(
                         "type: `{}` not found. try any of: {:?}",
@@ -87,11 +88,12 @@ pub fn generate(
     is_link: bool,
     fields: &[(String, String)],
     appinfo: &AppInfo,
+    custom_type_mapping: Option<String>
 ) -> Result<GenerateResults> {
     let pkg_name: &str = &appinfo.app_name;
     let ts = Utc::now();
 
-    let (columns, references) = get_columns_and_references(fields)?;
+    let (columns, references) = get_columns_and_references(fields, custom_type_mapping)?;
 
     let vars = json!({"name": name, "ts": ts, "pkg_name": pkg_name, "is_link": is_link, "columns": columns, "references": references});
     let gen_result = render_template(rrgen, Path::new("model"), &vars)?;
diff --git a/loco-gen/src/scaffold.rs b/loco-gen/src/scaffold.rs
index 4e03e18..5bb745c 100644
--- a/loco-gen/src/scaffold.rs
+++ b/loco-gen/src/scaffold.rs
@@ -14,11 +14,12 @@ pub fn generate(
     fields: &[(String, String)],
     kind: &ScaffoldKind,
     appinfo: &AppInfo,
+    custom_type_mapping: Option<String>,
 ) -> Result<GenerateResults> {
     // - scaffold is never a link table
     // - never run with migration_only, because the controllers will refer to the
     //   models. the models only arrive after migration and entities sync.
-    let mut gen_result = model::generate(rrgen, name, false, fields, appinfo)?;
+    let mut gen_result = model::generate(rrgen, name, false, fields, appinfo, custom_type_mapping.clone())?;
 
     let mut columns = Vec::new();
     for (fname, ftype) in fields {
@@ -40,7 +41,7 @@ pub fn generate(
                 //references.push((fname.to_string(), refname.clone()));
             }
             crate::infer::FieldType::Type(ftype) => {
-                let mappings = get_mappings();
+                let mappings = get_mappings(custom_type_mapping.clone());
                 let rust_type = mappings.rust_field(ftype.as_str()).ok_or_else(|| {
                     Error::Message(format!(
                         "type: `{}` not found. try any of: {:?}",
@@ -51,7 +52,7 @@ pub fn generate(
                 columns.push((fname.to_string(), rust_type.to_string(), ftype));
             }
             crate::infer::FieldType::TypeWithParameters(ftype, params) => {
-                let mappings = get_mappings();
+                let mappings = get_mappings(custom_type_mapping.clone());
                 let rust_type = mappings.rust_field(ftype.as_str()).ok_or_else(|| {
                     Error::Message(format!(
                         "type: `{}` not found. try any of: {:?}",
diff --git a/src/cli.rs b/src/cli.rs
index 63b68a7..8511606 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -1090,6 +1090,7 @@ fn handle_generate_command<H: Hooks>(
             &loco_gen::AppInfo {
                 app_name: H::app_name().to_string(),
             },
+            config.custom_type_mapping.clone(),
         )?;
         let messages = loco_gen::collect_messages(&get_result);
         println!("{messages}");
diff --git a/src/config.rs b/src/config.rs
index 69d1a73..9d90854 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -49,6 +49,7 @@ pub struct Config {
     pub server: Server,
     #[cfg(feature = "with-db")]
     pub database: Database,
+    pub custom_type_mapping: Option<String>,
     pub queue: Option<QueueConfig>,
     pub auth: Option<Auth>,
     #[serde(default)]

@qingmo
Copy link
Author

qingmo commented Jan 26, 2025

there are many special column types
Mysql:BLOB
pg: cidr

scaffold can not reach to their development speed, let developer manage those, scaffold just need to manage the minimal common types

@kaplanelad
Copy link
Contributor

I agree, this is the reason we decided to remove some of them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants