Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions dsl/QuickServiceDSL.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ component {
public any function process( required struct definition ) {
return variables.injector.getInstance(
name = "BaseService@quick",
initArguments = {
entity : variables.injector.getInstance( listRest( arguments.definition.dsl, ":" ) )
}
initArguments = { entity : variables.injector.getInstance( listRest( arguments.definition.dsl, ":" ) ) }
);
}

Expand Down
7 changes: 6 additions & 1 deletion models/BaseEntity.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -1527,7 +1527,12 @@ component accessors="true" {
if ( !isStruct( freshData ) || structKeyExists( freshData, "isQuickEntity" ) ) {
return freshData;
}
var entity = newEntity().hydrate( freshData );
// Snapshot rows use database column names, while hydrate() requires aliased keys.
// Use the same database-row hydration path as QuickBuilder.loadEntity().
var entity = newEntity()
.assignAttributesData( freshData )
.assignOriginalAttributes( freshData )
.markLoaded();
return hasRefreshQuery ? entity.set_refreshQuery( variables._refreshQuery ) : entity;
}

Expand Down
4 changes: 2 additions & 2 deletions resources/testing/FactoryManager.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ component {
variables.factories[ arguments.name ] = variables.wirebox.getInstance(
name = "#variables.factoryPath#.#arguments.name#Factory",
initArguments = {
entityProvider : variables.wirebox.getInstance(
entityProvider : variables.wirebox.getInstance(
dsl = "provider:#arguments.name#",
targetObject = this
),
context : variables.context
context : variables.context
}
);
}
Expand Down
18 changes: 18 additions & 0 deletions tests/resources/app/models/AliasedPrimaryKeyUser.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
component
extends ="quick.models.BaseEntity"
table ="users"
accessors="true"
{

property name="userID" column="id";
property name="username";
property name="firstName" column="first_name";
property name="lastName" column="last_name";

variables._key = "userID";

function scopeWithFullName( qb ) {
qb.appendVirtualAttribute( "fullName" ).selectRaw( "CONCAT(first_name, ' ', last_name) AS fullName" );
}

}
4 changes: 2 additions & 2 deletions tests/resources/factories/UserFactory.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ component extends="quick.resources.testing.Factory" {
}

any function administrator() {
return state( { type : "admin" } );
return state( { type : "admin" } );
}

any function wired() {
return state( { firstName : isObject( variables.wirebox ) ? "Injected" : "Missing" } );
return state( { firstName : isObject( variables.wirebox ) ? "Injected" : "Missing" } );
}

}
6 changes: 2 additions & 4 deletions tests/specs/integration/BaseEntity/ChildClassSpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -378,17 +378,15 @@ component extends="tests.resources.ModuleIntegrationSpec" {
// comment id 4 = internal comment
var internalComment = getInstance( "Comment" )
.findOrFail( 4 )
.update( { reason : "Super private, ya know?" } );
.update( { reason : "Super private, ya know?" } );

var uInternalComment = getInstance( "Comment" ).findOrFail( 4 );

expect( uInternalComment ).toBeInstanceOf( "internalComment" );
expect( uInternalComment.getReason() ).toBe( "Super private, ya know?" );

// comment id 5 = picture comment
var pictureComment = getInstance( "Comment" )
.findOrFail( 5 )
.update( { filename : "Lenna.jpeg" } );
var pictureComment = getInstance( "Comment" ).findOrFail( 5 ).update( { filename : "Lenna.jpeg" } );

var uPictureComment = getInstance( "Comment" ).findOrFail( 5 );

Expand Down
2 changes: 1 addition & 1 deletion tests/specs/integration/BaseEntity/ColumnsSpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ component extends="tests.resources.ModuleIntegrationSpec" {

it( "translates attributes to their column names", function() {
expect( function() {
getInstance( "Link" ).create( { url : "https://example.com" } );
getInstance( "Link" ).create( { url : "https://example.com" } );
} ).notToThrow();
} );

Expand Down
2 changes: 1 addition & 1 deletion tests/specs/integration/BaseEntity/GetSpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ component extends="tests.resources.ModuleIntegrationSpec" {
it( "passes query options when finding an entity by primary key", function() {
structDelete( request, "baseEntityGetSpecPreQBExecute" );

var user = getInstance( "User" ).find( 1, { datasource : "quick" } );
var user = getInstance( "User" ).find( 1, { datasource : "quick" } );
var executionsWithDatasource = request.baseEntityGetSpecPreQBExecute.filter( function( execution ) {
return execution.options.keyExists( "datasource" );
} );
Expand Down
6 changes: 3 additions & 3 deletions tests/specs/integration/BaseEntity/ReadOnlyEntitySpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ component extends="tests.resources.ModuleIntegrationSpec" {

it( "prevents create from being performed on new instances", function() {
expect( function() {
getInstance( "Referral" ).create( { type : "internal" } );
getInstance( "Referral" ).create( { type : "internal" } );
} ).toThrow( type = "QuickReadOnlyException" );
} );

Expand All @@ -27,13 +27,13 @@ component extends="tests.resources.ModuleIntegrationSpec" {
it( "prevents updates from being performed on existing instances", function() {
var referral = getInstance( "Referral" ).findOrFail( 1 );
expect( function() {
referral.update( { type : "external" } );
referral.update( { type : "external" } );
} ).toThrow( type = "QuickReadOnlyException" );
} );

it( "prevents mass updates from being performed on existing instances", function() {
expect( function() {
getInstance( "Referral" ).updateAll( { type : "external" } );
getInstance( "Referral" ).updateAll( { type : "external" } );
} ).toThrow( type = "QuickReadOnlyException" );
} );

Expand Down
8 changes: 4 additions & 4 deletions tests/specs/integration/BaseEntity/ReadOnlyPropertySpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ component extends="tests.resources.ModuleIntegrationSpec" {

it( "prevents create from setting read-only properties", function() {
expect( function() {
getInstance( "Link" ).create( { createdDate : now() } );
getInstance( "Link" ).create( { createdDate : now() } );
} ).toThrow( type = "QuickReadOnlyException" );
} );

Expand All @@ -45,20 +45,20 @@ component extends="tests.resources.ModuleIntegrationSpec" {
it( "prevents fill from being called containing a read-only property", function() {
var link = getInstance( "Link" ).findOrFail( 1 );
expect( function() {
link.fill( { createdDate : now() } );
link.fill( { createdDate : now() } );
} ).toThrow( type = "QuickReadOnlyException" );
} );

it( "prevents updates from being performed on a read-only property", function() {
var link = getInstance( "Link" ).findOrFail( 1 );
expect( function() {
link.update( { createdDate : now() } );
link.update( { createdDate : now() } );
} ).toThrow( type = "QuickReadOnlyException" );
} );

it( "prevents mass updates from being performed on read-only properties", function() {
expect( function() {
getInstance( "Link" ).updateAll( { createdDate : now() } );
getInstance( "Link" ).updateAll( { createdDate : now() } );
} ).toThrow( type = "QuickReadOnlyException" );
} );

Expand Down
15 changes: 15 additions & 0 deletions tests/specs/integration/BaseEntity/RefreshSnapshotSpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ component extends="tests.resources.ModuleIntegrationSpec" {

function run() {
describe( "Result-set refresh snapshots", function() {
it( "retrieves fresh projected entities with aliased primary keys", function() {
var user = getInstance( "AliasedPrimaryKeyUser" ).withFullName().findOrFail( 1 );
queryExecute( "UPDATE `users` SET `first_name` = ? WHERE `id` = ?", [ "Aliased", 1 ] );

var fresh = user.fresh();
expect( fresh.getUserID() ).toBe( 1 );
expect( fresh.getFullName() ).toBe( "Aliased Peterson" );
expect( fresh.isLoaded() ).toBeTrue();
expect( fresh.isDirty( "userID" ) ).toBeFalse();
expect( fresh.isDirty( "firstName" ) ).toBeFalse();
expect( fresh.get_refreshQuery() ).toBeSameInstanceAs( user.get_refreshQuery() );
expect( fresh.fresh().getUserID() ).toBe( 1 );
expect( user.getFirstName() ).toBe( "Eric" );
} );

it( "shares an isolated projection snapshot across get results", function() {
assertSharedSnapshot( "get" );
} );
Expand Down
12 changes: 3 additions & 9 deletions tests/specs/integration/BaseServiceSpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,12 @@ component extends="tests.resources.ModuleIntegrationSpec" {
describe( "instantiation", function() {
it( "can be instantiated with an entity", function() {
var user = getInstance( "User" );
var service = getInstance(
name = "BaseService@quick",
initArguments = { entity : user }
);
var service = getInstance( name = "BaseService@quick", initArguments = { entity : user } );
expect( service.entityName() ).toBe( "User" );
} );

it( "can be instantiated with a wirebox mapping", function() {
var service = getInstance(
name = "BaseService@quick",
initArguments = { entity : "User" }
);
var service = getInstance( name = "BaseService@quick", initArguments = { entity : "User" } );
expect( service.entityName() ).toBe( "User" );
} );

Expand Down Expand Up @@ -68,7 +62,7 @@ component extends="tests.resources.ModuleIntegrationSpec" {

var users = variables.service
.whereNotNull( "created_date" )
.get( options = { datasource : "quick" } );
.get( options = { datasource : "quick" } );

expect( users ).toBeArray();
expect( request.baseServiceSpecPreQBExecute ).toHaveLength( 1 );
Expand Down
8 changes: 4 additions & 4 deletions tests/specs/integration/CBORMCompatEntitySpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ component extends="tests.resources.ModuleIntegrationSpec" {

it( "list (with arguments)", function() {
var users = user.list(
criteria = { lastName : "Doe" },
criteria = { lastName : "Doe" },
sortOrder = "username",
max = 2,
offset = 1,
Expand Down Expand Up @@ -101,7 +101,7 @@ component extends="tests.resources.ModuleIntegrationSpec" {
} );

it( "findWhere", function() {
var john = user.findWhere( { firstName : "John" } );
var john = user.findWhere( { firstName : "John" } );
expect( john.getId() ).toBe( 2 );
expect( john.getUsername() ).toBe( "johndoe" );
} );
Expand Down Expand Up @@ -178,14 +178,14 @@ component extends="tests.resources.ModuleIntegrationSpec" {
} );

it( "new (with properties)", function() {
var newUser = user.new( { username : "new_username" } );
var newUser = user.new( { username : "new_username" } );
expect( newUser.isLoaded() ).toBeFalse();
expect( newUser.getUsername() ).toBe( "new_username" );
} );

it( "populate", function() {
var newUser = user.new();
newUser.populate( { username : "new_username" } );
newUser.populate( { username : "new_username" } );
expect( newUser.getUsername() ).toBe( "new_username" );
} );

Expand Down
14 changes: 7 additions & 7 deletions tests/specs/integration/FactorySpec.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ component extends="tests.resources.ModuleIntegrationSpec" {
function run() {
describe( "Quick model factories", function() {
it( "makes unsaved entities from defaults and explicit overrides", function() {
var user = newFactoryManager( { suffix : "make" } )
var user = newFactoryManager( { suffix : "make" } )
.factory( "User" )
.make( { firstName : "Overridden" } );
.make( { firstName : "Overridden" } );

expect( user ).toBeInstanceOf( "User" );
expect( user.isLoaded() ).toBeFalse();
Expand All @@ -16,17 +16,17 @@ component extends="tests.resources.ModuleIntegrationSpec" {
} );

it( "combines counts, named states, sequences, and persisted Quick entities", function() {
var users = newFactoryManager( { suffix : "sequence" } )
var users = newFactoryManager( { suffix : "sequence" } )
.factory( "User" )
.count( 3 )
.administrator()
.state( function( attributes, context ) {
return { firstName : "State #context.index#" };
return { firstName : "State #context.index#" };
} )
.sequence( [
{ lastName : "Sequence A" },
{ lastName : "Sequence A" },
function( attributes, context ) {
return { lastName : "Sequence #context.index#" };
return { lastName : "Sequence #context.index#" };
}
] )
.create();
Expand Down Expand Up @@ -55,7 +55,7 @@ component extends="tests.resources.ModuleIntegrationSpec" {
var created = [];
var user = newFactoryManager()
.factory( "User" )
.state( { username : "factory-callback" } )
.state( { username : "factory-callback" } )
.afterMaking( function( entity, attributes ) {
arrayAppend( made, attributes.username );
} )
Expand Down
Loading