green_barrel/models.rs
1//! Adapts the Structure for database queries using a programmatic or web interface.
2
3pub mod addition;
4pub mod caching;
5pub mod control;
6pub mod converters;
7pub mod db_query_api;
8pub mod fixtures;
9pub mod helpers;
10pub mod hooks;
11pub mod output_data;
12pub mod validation;
13
14use async_trait::async_trait;
15
16use mongodb::{
17 bson::{doc, document::Document, oid::ObjectId},
18 Client,
19};
20use serde_json::{json, value::Value};
21use std::error::Error;
22
23use crate::models::helpers::Meta;
24
25/// Model options and field type map for Form.
26// *************************************************************************************************
27#[async_trait(?Send)]
28pub trait Main {
29 /// Get model key
30 /// ( to access model metadata in cache ).
31 // ---------------------------------------------------------------------------------------------
32 fn key() -> Result<String, Box<dyn Error>>;
33
34 /// Model instance from `create` method, convert to intermediate state `serde_json::value::Value`,
35 /// with the addition of Html-ID and data validation.
36 // ---------------------------------------------------------------------------------------------
37 fn custom_to_json_val() -> Result<Value, Box<dyn Error>>
38 where
39 Self: serde::de::DeserializeOwned + Sized;
40
41 /// Generate metadata of Model.
42 // ---------------------------------------------------------------------------------------------
43 fn generate_metadata() -> Result<Meta, Box<dyn Error>>
44 where
45 Self: serde::de::DeserializeOwned + Sized;
46
47 /// Getter and Setter for field `hash`.
48 // ---------------------------------------------------------------------------------------------
49 fn hash(&self) -> String;
50 fn set_hash(&mut self, value: String);
51
52 /// ObjectId from hash field.
53 // ---------------------------------------------------------------------------------------------
54 fn obj_id(&self) -> Result<Option<ObjectId>, Box<dyn Error>>;
55
56 /// ObjectId to hash field.
57 // ---------------------------------------------------------------------------------------------
58 fn set_obj_id(&mut self, object_id: ObjectId);
59
60 /// Getter and Setter for field `created_at`.
61 // ---------------------------------------------------------------------------------------------
62 fn created_at(&self) -> String;
63 fn set_created_at(&mut self, value: String);
64
65 /// Getter and Setter for field `updated_at`.
66 // ---------------------------------------------------------------------------------------------
67 fn updated_at(&self) -> String;
68 fn set_updated_at(&mut self, value: String);
69
70 /// Serializing the model instance to serde_json::Value format.
71 // ---------------------------------------------------------------------------------------------
72 fn self_to_json_val(&self) -> Result<Value, Box<dyn Error>>;
73
74 /// Enrich field type map with values for dynamic fields type.
75 // ---------------------------------------------------------------------------------------------
76 async fn injection(
77 client: &Client,
78 app_name: &str,
79 unique_app_key: &str,
80 collection_name: &str,
81 model_json: &mut Value,
82 fields_name: &Vec<String>,
83 ) -> Result<(), Box<dyn Error>>
84 where
85 Self: serde::de::DeserializeOwned + Sized,
86 {
87 // Init the name of the project's technical database.
88 let db_green_tech: String = format!("green_tech__{app_name}__{unique_app_key}");
89 // Access to the collection with values for dynamic fields type.
90 let collection = client
91 .database(&db_green_tech)
92 .collection::<Document>("dynamic_fields");
93 // Filter for searching a document.
94 let filter = doc! {
95 "collection": collection_name
96 };
97 // Get a document with values for dynamic fields type.
98 if let Some(doc) = collection.find_one(filter, None).await? {
99 let dyn_values_doc = doc.get_document("fields")?;
100 // Updating the `choices` parameter for fields with a dynamic field type.
101 for field_name in fields_name {
102 let field_type = model_json
103 .get(field_name)
104 .unwrap()
105 .get("field_type")
106 .unwrap()
107 .as_str()
108 .unwrap();
109 //
110 if field_type.contains("Dyn") {
111 let arr = dyn_values_doc.get_array(field_name)?;
112 if field_type.contains("Text") {
113 let choices = arr
114 .iter()
115 .map(|item| {
116 let arr = item.as_array().unwrap();
117 (
118 arr[0].as_str().unwrap().to_string(),
119 arr[1].as_str().unwrap().to_string(),
120 )
121 })
122 .collect::<Vec<(String, String)>>();
123 *model_json
124 .get_mut(field_name)
125 .unwrap()
126 .get_mut("choices")
127 .unwrap() = json!(choices);
128 } else if field_type.contains("I32") {
129 let choices = arr
130 .iter()
131 .map(|item| {
132 let arr = item.as_array().unwrap();
133 (
134 arr[0].as_i32().unwrap(),
135 arr[1].as_str().unwrap().to_string(),
136 )
137 })
138 .collect::<Vec<(i32, String)>>();
139 *model_json
140 .get_mut(field_name)
141 .unwrap()
142 .get_mut("choices")
143 .unwrap() = json!(choices);
144 } else if field_type.contains("U32") || field_type.contains("I64") {
145 let choices = arr
146 .iter()
147 .map(|item| {
148 let arr = item.as_array().unwrap();
149 (
150 arr[0].as_i64().unwrap(),
151 arr[1].as_str().unwrap().to_string(),
152 )
153 })
154 .collect::<Vec<(i64, String)>>();
155 *model_json
156 .get_mut(field_name)
157 .unwrap()
158 .get_mut("choices")
159 .unwrap() = json!(choices);
160 } else if field_type.contains("F64") {
161 let choices = arr
162 .iter()
163 .map(|item| {
164 let arr = item.as_array().unwrap();
165 (
166 arr[0].as_f64().unwrap(),
167 arr[1].as_str().unwrap().to_string(),
168 )
169 })
170 .collect::<Vec<(f64, String)>>();
171 *model_json
172 .get_mut(field_name)
173 .unwrap()
174 .get_mut("choices")
175 .unwrap() = json!(choices);
176 } else {
177 Err(format!(
178 "Model: {} > Method: `injection()` => \
179 Invalid data type.",
180 Self::generate_metadata()?.model_name,
181 ))?
182 }
183 }
184 }
185 }
186
187 Ok(())
188 }
189}