diff --git a/models/BaseEntity.cfc b/models/BaseEntity.cfc index 8900ec4..6a070b5 100644 --- a/models/BaseEntity.cfc +++ b/models/BaseEntity.cfc @@ -2777,6 +2777,25 @@ component accessors="true" { relationship.relationshipClass != "BelongsTo" && relationship.relationshipClass != "PolymorphicBelongsTo" ) { + if ( !isLoaded() ) { + var relationshipValue = arguments.missingMethodArguments[ 1 ]; + var relatedEntity = relationship.getRelated(); + var filledRelationship = relationshipValue; + if ( isArray( relationshipValue ) ) { + filledRelationship = []; + for ( var value in relationshipValue ) { + filledRelationship.append( + isStruct( value ) && !structKeyExists( value, "isQuickEntity" ) + ? relatedEntity.newEntity().fill( value ) + : value + ); + } + } else if ( isStruct( relationshipValue ) && !structKeyExists( relationshipValue, "isQuickEntity" ) ) { + filledRelationship = relatedEntity.newEntity().fill( relationshipValue ); + } + assignRelationship( relationshipName, filledRelationship ); + return filledRelationship; + } guardAgainstNotLoaded( "This instance is not loaded so it cannot set the [#relationshipName#] relationship. " & "Save the new entity first before trying to save related entities." diff --git a/tests/specs/integration/BaseEntity/CreateSpec.cfc b/tests/specs/integration/BaseEntity/CreateSpec.cfc index e294a3c..9344aac 100644 --- a/tests/specs/integration/BaseEntity/CreateSpec.cfc +++ b/tests/specs/integration/BaseEntity/CreateSpec.cfc @@ -36,6 +36,25 @@ component extends="tests.resources.ModuleIntegrationSpec" { ).notToBeNull(); } ); + it( "creates only the root while retaining filled relationships in memory", function() { + var user = getInstance( "User" ).create( { + "username" : "aggregate-user", + "first_name" : "Aggregate", + "last_name" : "User", + "password" : hash( "password" ), + "posts" : [ + { "body" : "First child" }, + { "body" : "Second child" } + ] + } ); + + expect( user.isLoaded() ).toBeTrue(); + expect( user.getPosts() ).toHaveLength( 2 ); + expect( user.getPosts()[ 1 ].isLoaded() ).toBeFalse(); + expect( user.getPosts()[ 2 ].isLoaded() ).toBeFalse(); + expect( user.fresh().getPosts() ).toBeEmpty(); + } ); + it( "can create a new entity with a json cast", () => { var newTheme = getInstance( "Theme" ).create( { slug : "theme-new", diff --git a/tests/specs/integration/BaseEntity/FillSpec.cfc b/tests/specs/integration/BaseEntity/FillSpec.cfc index 287c379..1047e2e 100644 --- a/tests/specs/integration/BaseEntity/FillSpec.cfc +++ b/tests/specs/integration/BaseEntity/FillSpec.cfc @@ -60,6 +60,24 @@ component extends="tests.resources.ModuleIntegrationSpec" { } ).notToThrow(); expect( user.isNullAttribute( "updatedDate" ) ).toBeTrue(); } ); + + it( "can fill relationships on a new entity without persisting the aggregate", function() { + var user = getInstance( "User" ).fill( { + "posts" : [ + getInstance( "Post" ).fill( { "body" : "Entity child" } ), + { "body" : "Struct child" } + ] + } ); + + expect( user.isLoaded() ).toBeFalse(); + expect( user.getPosts() ).toHaveLength( 2 ); + expect( user.getPosts()[ 1 ] ).toBeInstanceOf( "Post" ); + expect( user.getPosts()[ 1 ].isLoaded() ).toBeFalse(); + expect( user.getPosts()[ 1 ].getBody() ).toBe( "Entity child" ); + expect( user.getPosts()[ 2 ] ).toBeInstanceOf( "Post" ); + expect( user.getPosts()[ 2 ].isLoaded() ).toBeFalse(); + expect( user.getPosts()[ 2 ].getBody() ).toBe( "Struct child" ); + } ); } ); } diff --git a/tests/specs/integration/GoodErrorMessagesSpec.cfc b/tests/specs/integration/GoodErrorMessagesSpec.cfc index b70a0ad..69abe5c 100644 --- a/tests/specs/integration/GoodErrorMessagesSpec.cfc +++ b/tests/specs/integration/GoodErrorMessagesSpec.cfc @@ -64,18 +64,17 @@ component extends="tests.resources.ModuleIntegrationSpec" { skip = server.keyExists( "boxlang" ) ); - it( "throws a helpful error message when trying to set a belongsToMany relationship when the relationship is not loaded", function() { - expect( function() { - getInstance( "Post" ).create( { - "user_id" : 1, - "body" : "A new post body", - "publishedDate" : now(), - "tags" : [ 1, 2 ] - } ); - } ).toThrow( - type = "QuickEntityNotLoaded", - regex = "This instance is not loaded so it cannot set the \[tags\] relationship\. Save the new entity first before trying to save related entities\." - ); + it( "does not persist a filled belongsToMany relationship when creating the parent", function() { + var post = getInstance( "Post" ).create( { + "user_id" : 1, + "body" : "A new post body", + "publishedDate" : now(), + "tags" : [ 1, 2 ] + } ); + + expect( post.isLoaded() ).toBeTrue(); + expect( post.getTags() ).toBe( [ 1, 2 ] ); + expect( post.fresh().getTags() ).toBeEmpty(); } ); } ); }