22
33use async_trait:: async_trait;
44use sea_orm:: sea_query:: OnConflict ;
5+ use std:: future:: Future ;
6+ use std:: pin:: Pin ;
57
68use crate :: callbacks:: { AfterCreateDispatch , AfterDeleteDispatch , AfterUpdateDispatch , BeforeCreateDispatch , BeforeDeleteDispatch , BeforeUpdateDispatch } ;
79use crate :: error:: { Error , Result } ;
810use crate :: internal:: { EntityTrait , InternalModel , IntoActiveModel , translate_error} ;
911
1012use super :: Model ;
1113
14+ type OneRelationSaveOp = Box <
15+ dyn FnOnce ( serde_json:: Value ) -> Pin < Box < dyn Future < Output = Result < serde_json:: Value > > > > ,
16+ > ;
17+
18+ type ManyRelationSaveOp = Box <
19+ dyn FnOnce ( serde_json:: Value ) -> Pin < Box < dyn Future < Output = Result < Vec < serde_json:: Value > > > > > ,
20+ > ;
21+
1222fn parent_primary_key_json < M : Model > ( parent : & M ) -> serde_json:: Value {
1323 let pk = parent. primary_key ( ) ;
1424 serde_json:: Value :: String ( format ! ( "{}" , pk) )
@@ -163,6 +173,54 @@ where
163173 reorder_models_by_primary_key ( fetched, & pk_order)
164174}
165175
176+ async fn save_related_model_as_json < R > (
177+ related : R ,
178+ foreign_key : String ,
179+ parent_pk_value : serde_json:: Value ,
180+ ) -> Result < serde_json:: Value >
181+ where
182+ R : Model ,
183+ {
184+ let related = apply_foreign_key ( related, & foreign_key, & parent_pk_value) ?;
185+ let related = related. save ( ) . await ?;
186+ serde_json:: to_value ( & related)
187+ . map_err ( |e| Error :: conversion ( format ! ( "Failed to serialize related model: {}" , e) ) )
188+ }
189+
190+ async fn save_related_models_as_json < R > (
191+ related : Vec < R > ,
192+ foreign_key : String ,
193+ parent_pk_value : serde_json:: Value ,
194+ ) -> Result < Vec < serde_json:: Value > >
195+ where
196+ R : Model ,
197+ <<R as InternalModel >:: Entity as EntityTrait >:: Model : IntoActiveModel < R :: ActiveModel > ,
198+ {
199+ if related. is_empty ( ) {
200+ return Ok ( Vec :: new ( ) ) ;
201+ }
202+
203+ let mut prepared_related = Vec :: with_capacity ( related. len ( ) ) ;
204+ for item in related {
205+ let mut item = apply_foreign_key ( item, & foreign_key, & parent_pk_value) ?;
206+ ( & mut item) . run_before_create ( ) ?;
207+ prepared_related. push ( item) ;
208+ }
209+
210+ let saved_related = R :: insert_all ( prepared_related) . await ?;
211+ let mut saved_json = Vec :: with_capacity ( saved_related. len ( ) ) ;
212+ for item in saved_related {
213+ ( & item) . run_after_create ( ) ?;
214+ saved_json. push (
215+ serde_json:: to_value ( & item) . map_err ( |e| {
216+ Error :: conversion ( format ! ( "Failed to serialize related model: {}" , e) )
217+ } ) ?,
218+ ) ;
219+ }
220+
221+ Ok ( saved_json)
222+ }
223+
166224/// Extension trait for cascade save operations.
167225#[ async_trait]
168226pub trait NestedSave : Model {
@@ -305,8 +363,8 @@ impl<M: Model> NestedSave for M {}
305363/// Builder for nested/cascade saves.
306364pub struct NestedSaveBuilder < M : Model > {
307365 parent : M ,
308- one_relations : Vec < ( serde_json :: Value , String ) > ,
309- many_relations : Vec < ( Vec < serde_json :: Value > , String ) > ,
366+ one_relations : Vec < OneRelationSaveOp > ,
367+ many_relations : Vec < ManyRelationSaveOp > ,
310368}
311369
312370impl < M : Model > NestedSaveBuilder < M > {
@@ -318,20 +376,30 @@ impl<M: Model> NestedSaveBuilder<M> {
318376 }
319377 }
320378
321- pub fn with_one < R : Model > ( mut self , related : R , foreign_key : & str ) -> Self {
322- if let Ok ( json) = serde_json:: to_value ( & related) {
323- self . one_relations . push ( ( json, foreign_key. to_string ( ) ) ) ;
324- }
379+ pub fn with_one < R : Model + ' static > ( mut self , related : R , foreign_key : & str ) -> Self {
380+ let foreign_key = foreign_key. to_string ( ) ;
381+ self . one_relations . push ( Box :: new ( move |parent_pk_value| {
382+ Box :: pin ( save_related_model_as_json (
383+ related,
384+ foreign_key,
385+ parent_pk_value,
386+ ) )
387+ } ) ) ;
325388 self
326389 }
327390
328- pub fn with_many < R : Model > ( mut self , related : Vec < R > , foreign_key : & str ) -> Self {
329- let json_values: Vec < serde_json:: Value > = related
330- . into_iter ( )
331- . filter_map ( |r| serde_json:: to_value ( & r) . ok ( ) )
332- . collect ( ) ;
333- self . many_relations
334- . push ( ( json_values, foreign_key. to_string ( ) ) ) ;
391+ pub fn with_many < R : Model + ' static > ( mut self , related : Vec < R > , foreign_key : & str ) -> Self
392+ where
393+ <<R as InternalModel >:: Entity as EntityTrait >:: Model : IntoActiveModel < R :: ActiveModel > ,
394+ {
395+ let foreign_key = foreign_key. to_string ( ) ;
396+ self . many_relations . push ( Box :: new ( move |parent_pk_value| {
397+ Box :: pin ( save_related_models_as_json (
398+ related,
399+ foreign_key,
400+ parent_pk_value,
401+ ) )
402+ } ) ) ;
335403 self
336404 }
337405
@@ -345,30 +413,12 @@ impl<M: Model> NestedSaveBuilder<M> {
345413
346414 let mut saved_json = Vec :: new ( ) ;
347415
348- for ( mut json, fk) in self . one_relations {
349- if let serde_json:: Value :: Object ( ref mut map) = json {
350- let pk_str = pk_value. as_str ( ) . unwrap_or_default ( ) ;
351- if let Ok ( pk_i64) = pk_str. parse :: < i64 > ( ) {
352- map. insert ( fk, serde_json:: json!( pk_i64) ) ;
353- } else {
354- map. insert ( fk, pk_value. clone ( ) ) ;
355- }
356- }
357- saved_json. push ( json) ;
416+ for save_relation in self . one_relations {
417+ saved_json. push ( save_relation ( pk_value. clone ( ) ) . await ?) ;
358418 }
359419
360- for ( items, fk) in self . many_relations {
361- for mut json in items {
362- if let serde_json:: Value :: Object ( ref mut map) = json {
363- let pk_str = pk_value. as_str ( ) . unwrap_or_default ( ) ;
364- if let Ok ( pk_i64) = pk_str. parse :: < i64 > ( ) {
365- map. insert ( fk. clone ( ) , serde_json:: json!( pk_i64) ) ;
366- } else {
367- map. insert ( fk. clone ( ) , pk_value. clone ( ) ) ;
368- }
369- }
370- saved_json. push ( json) ;
371- }
420+ for save_relations in self . many_relations {
421+ saved_json. extend ( save_relations ( pk_value. clone ( ) ) . await ?) ;
372422 }
373423
374424 Ok ( ( parent, saved_json) )
0 commit comments