1#[macro_export]
2#[doc(hidden)]
3macro_rules! model_timestamps_fields {
4 (true) => {
5 pub created_at: Option<DateTime>,
6 pub updated_at: Option<DateTime>,
7 };
8 (false) => {};
9}
10
11#[macro_export]
12#[doc(hidden)]
13macro_rules! model_behavior_impl {
14 (true) => {
15 #[$crate::async_trait]
16 impl $crate::sea_orm::entity::prelude::ActiveModelBehavior for ActiveModel {
17 async fn before_save<C>(mut self, _db: &C, insert: bool) -> Result<Self, $crate::sea_orm::DbErr>
18 where
19 C: $crate::sea_orm::ConnectionTrait,
20 {
21 let now = $crate::chrono::Local::now().naive_local();
22 if insert {
23 self.created_at = $crate::sea_orm::ActiveValue::Set(Some(now));
24 }
25 self.updated_at = $crate::sea_orm::ActiveValue::Set(Some(now));
26 Ok(self)
27 }
28 }
29 };
30 (false) => {
31 impl $crate::sea_orm::entity::prelude::ActiveModelBehavior for ActiveModel {}
32 };
33}
34
35#[macro_export]
36#[doc(hidden)]
37macro_rules! model_impl {
38 (
40 table: $table_name:expr,
41 timestamps: true,
42 fillable: [ $($fill:ident),* ],
43 guarded: [ $($guard:ident),* ],
44 Model {
45 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
46 }
47 ) => {
48 #[derive(Clone, Debug, PartialEq, $crate::sea_orm::entity::prelude::DeriveEntityModel, $crate::serde::Serialize, $crate::serde::Deserialize)]
49 #[sea_orm(table_name = $table_name)]
50 pub struct Model {
51 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
52 pub created_at: Option<DateTime>,
53 pub updated_at: Option<DateTime>,
54 }
55
56 #[derive(Copy, Clone, Debug, $crate::sea_orm::entity::prelude::EnumIter, $crate::sea_orm::entity::prelude::DeriveRelation)]
57 pub enum Relation {}
58
59 $crate::model_behavior_impl!(true);
60
61 impl Entity {
62 pub async fn create<C>(db: &C, data: $crate::serde_json::Value) -> Result<Model, $crate::sea_orm::DbErr>
63 where
64 C: $crate::sea_orm::ConnectionTrait,
65 {
66 let active = ActiveModel::fill(&data)?;
67 <ActiveModel as $crate::sea_orm::ActiveModelTrait>::insert(active, db).await
68 }
69 }
70
71 impl Model {
72 pub async fn create<C>(db: &C, data: $crate::serde_json::Value) -> Result<Self, $crate::sea_orm::DbErr>
73 where
74 C: $crate::sea_orm::ConnectionTrait,
75 {
76 let active = ActiveModel::fill(&data)?;
77 <ActiveModel as $crate::sea_orm::ActiveModelTrait>::insert(active, db).await
78 }
79 }
80
81 impl ActiveModel {
82 pub fn fill(json: &$crate::serde_json::Value) -> Result<Self, $crate::sea_orm::DbErr> {
83 let mut active: Self = ::std::default::Default::default();
84 if let Some(obj) = json.as_object() {
85 let fillable: Vec<&str> = vec![ $( stringify!($fill) ),* ];
86 let guarded: Vec<&str> = vec![ $( stringify!($guard) ),* ];
87
88 $(
89 let key = stringify!($field_name);
90 let is_allowed = if !fillable.is_empty() {
91 fillable.contains(&key)
92 } else if !guarded.is_empty() {
93 !guarded.contains(&key)
94 } else {
95 true
96 };
97
98 if is_allowed {
99 if let Some(val) = obj.get(key) {
100 let parsed: $field_type = $crate::serde_json::from_value(val.clone())
101 .map_err(|e| $crate::sea_orm::DbErr::Custom(format!("Json Error: {}", e)))?;
102 active.$field_name = $crate::sea_orm::ActiveValue::Set(parsed);
103 }
104 }
105 )*
106 }
107 Ok(active)
108 }
109 }
110 };
111
112 (
114 table: $table_name:expr,
115 timestamps: false,
116 fillable: [ $($fill:ident),* ],
117 guarded: [ $($guard:ident),* ],
118 Model {
119 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
120 }
121 ) => {
122 #[derive(Clone, Debug, PartialEq, $crate::sea_orm::entity::prelude::DeriveEntityModel, $crate::serde::Serialize, $crate::serde::Deserialize)]
123 #[sea_orm(table_name = $table_name)]
124 pub struct Model {
125 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
126 }
127
128 #[derive(Copy, Clone, Debug, $crate::sea_orm::entity::prelude::EnumIter, $crate::sea_orm::entity::prelude::DeriveRelation)]
129 pub enum Relation {}
130
131 $crate::model_behavior_impl!(false);
132
133 impl Entity {
134 pub async fn create<C>(db: &C, data: $crate::serde_json::Value) -> Result<Model, $crate::sea_orm::DbErr>
135 where
136 C: $crate::sea_orm::ConnectionTrait,
137 {
138 let active = ActiveModel::fill(&data)?;
139 <ActiveModel as $crate::sea_orm::ActiveModelTrait>::insert(active, db).await
140 }
141 }
142
143 impl Model {
144 pub async fn create<C>(db: &C, data: $crate::serde_json::Value) -> Result<Self, $crate::sea_orm::DbErr>
145 where
146 C: $crate::sea_orm::ConnectionTrait,
147 {
148 let active = ActiveModel::fill(&data)?;
149 <ActiveModel as $crate::sea_orm::ActiveModelTrait>::insert(active, db).await
150 }
151 }
152
153 impl ActiveModel {
154 pub fn fill(json: &$crate::serde_json::Value) -> Result<Self, $crate::sea_orm::DbErr> {
155 let mut active: Self = ::std::default::Default::default();
156 if let Some(obj) = json.as_object() {
157 let fillable: Vec<&str> = vec![ $( stringify!($fill) ),* ];
158 let guarded: Vec<&str> = vec![ $( stringify!($guard) ),* ];
159
160 $(
161 let key = stringify!($field_name);
162 let is_allowed = if !fillable.is_empty() {
163 fillable.contains(&key)
164 } else if !guarded.is_empty() {
165 !guarded.contains(&key)
166 } else {
167 true
168 };
169
170 if is_allowed {
171 if let Some(val) = obj.get(key) {
172 let parsed: $field_type = $crate::serde_json::from_value(val.clone())
173 .map_err(|e| $crate::sea_orm::DbErr::Custom(format!("Json Error: {}", e)))?;
174 active.$field_name = $crate::sea_orm::ActiveValue::Set(parsed);
175 }
176 }
177 )*
178 }
179 Ok(active)
180 }
181 }
182 };
183}
184
185#[macro_export]
186macro_rules! model {
187 (
189 table: $table_name:expr,
190 timestamps: true,
191 fillable: [ $($fill:ident),* ],
192 guarded: [ $($guard:ident),* ],
193 Model {
194 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
195 }
196 ) => {
197 $crate::model_impl! {
198 table: $table_name,
199 timestamps: true,
200 fillable: [ $($fill),* ],
201 guarded: [ $($guard),* ],
202 Model {
203 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
204 }
205 }
206 };
207
208 (
210 table: $table_name:expr,
211 timestamps: false,
212 fillable: [ $($fill:ident),* ],
213 guarded: [ $($guard:ident),* ],
214 Model {
215 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
216 }
217 ) => {
218 $crate::model_impl! {
219 table: $table_name,
220 timestamps: false,
221 fillable: [ $($fill),* ],
222 guarded: [ $($guard),* ],
223 Model {
224 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
225 }
226 }
227 };
228
229 (
231 table: $table_name:expr,
232 timestamps: $ts:ident,
233 fillable: [ $($fill:ident),* ],
234 Model {
235 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
236 }
237 ) => {
238 $crate::model! {
239 table: $table_name,
240 timestamps: $ts,
241 fillable: [ $($fill),* ],
242 guarded: [ ],
243 Model {
244 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
245 }
246 }
247 };
248
249 (
251 table: $table_name:expr,
252 timestamps: $ts:ident,
253 guarded: [ $($guard:ident),* ],
254 Model {
255 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
256 }
257 ) => {
258 $crate::model! {
259 table: $table_name,
260 timestamps: $ts,
261 fillable: [ ],
262 guarded: [ $($guard),* ],
263 Model {
264 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
265 }
266 }
267 };
268
269 (
271 table: $table_name:expr,
272 timestamps: $ts:ident,
273 Model {
274 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
275 }
276 ) => {
277 $crate::model! {
278 table: $table_name,
279 timestamps: $ts,
280 fillable: [ ],
281 guarded: [ ],
282 Model {
283 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
284 }
285 }
286 };
287
288 (
290 table: $table_name:expr,
291 fillable: [ $($fill:ident),* ],
292 guarded: [ $($guard:ident),* ],
293 Model {
294 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
295 }
296 ) => {
297 $crate::model! {
298 table: $table_name,
299 timestamps: true,
300 fillable: [ $($fill),* ],
301 guarded: [ $($guard),* ],
302 Model {
303 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
304 }
305 }
306 };
307
308 (
310 table: $table_name:expr,
311 fillable: [ $($fill:ident),* ],
312 Model {
313 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
314 }
315 ) => {
316 $crate::model! {
317 table: $table_name,
318 timestamps: true,
319 fillable: [ $($fill),* ],
320 guarded: [ ],
321 Model {
322 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
323 }
324 }
325 };
326
327 (
329 table: $table_name:expr,
330 guarded: [ $($guard:ident),* ],
331 Model {
332 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
333 }
334 ) => {
335 $crate::model! {
336 table: $table_name,
337 timestamps: true,
338 fillable: [ ],
339 guarded: [ $($guard),* ],
340 Model {
341 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
342 }
343 }
344 };
345
346 (
348 table: $table_name:expr,
349 Model {
350 $($(#[$field_meta:meta])* $field_vis:vis $field_name:ident : $field_type:ty),* $(,)?
351 }
352 ) => {
353 $crate::model! {
354 table: $table_name,
355 timestamps: true,
356 fillable: [ ],
357 guarded: [ ],
358 Model {
359 $($(#[$field_meta])* $field_vis $field_name : $field_type,)*
360 }
361 }
362 };
363}
364
365#[macro_export]
366macro_rules! seeder {
367 (
368 $name:ident,
369 run($db:ident) $body:block
370 ) => {
371 pub struct $name;
372
373 #[$crate::async_trait]
374 impl $crate::seeder::SeederTrait for $name {
375 async fn run(&self, $db: &$crate::sea_orm::DatabaseConnection) -> Result<(), $crate::sea_orm::DbErr> {
376 $body
377 }
378 }
379 };
380
381 (
382 run($db:ident) $body:block
383 ) => {
384 $crate::seeder! {
385 DatabaseSeeder,
386 run($db) $body
387 }
388 };
389}