Skip to content
Closed
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
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,22 @@ component extends="quick.models.BaseEntity" {

Query caching stores database results, not live Quick entities or loaded relationships. Cache lifetime and invalidation are managed by the CFML engine, so use short lifetimes for data that Quick or another process may update. For application-specific invalidation or distributed caching, cache entity mementos in CacheBox at the service layer and rehydrate them through Quick's public APIs.

### Seeding a Loaded Relationship

Use `assignRelationship` when you already have the related value and want Quick to return it without running the relationship query. This is especially useful after creating related records:

```javascript
var user = getInstance( "User" ).findOrFail( 1 );
var post = user.posts().create( { "body" : "A new post" } );

// `getPosts()` now returns this array without querying the database.
user.assignRelationship( "posts", [ post ] );
```

Pass a Quick entity for a singular relationship and an array for a collection relationship. Assigning a value replaces any previously loaded value and marks the relationship as loaded. `assignRelationship` only changes the in-memory entity; it does not save either entity, update foreign keys, attach pivot records, or validate that the value matches the relationship type.

Call `clearRelationship( "posts" )` to discard the assigned value and loaded marker. The next relationship accessor call can then lazy load the relationship normally, when lazy loading is enabled.

### Tests and Contributing

To run the tests, first clone this repo and run a `box install`.
Expand Down
13 changes: 9 additions & 4 deletions models/BaseEntity.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -1559,10 +1559,15 @@ component accessors="true" {
}

/**
* Assigns a result to a relationship.
*
* @name The name of the relationship to assign.
* @value The result for the relationship.
* Assigns a value to an entity relationship and marks that relationship as loaded.
* Accessing the relationship after assignment returns the supplied value without
* executing its relationship query. This only changes the in-memory entity: it
* does not persist the relationship, synchronize keys, or validate the value.
* Use `clearRelationship( name )` to remove the assigned value and loaded marker.
*
* @name The relationship method name to seed.
* @value The value to return for the relationship, usually an entity for a
* singular relationship or an array for a collection relationship.
*
* @return quick.models.BaseEntity
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,24 @@ component extends="tests.resources.ModuleIntegrationSpec" {
expect( elpete2FavoritePost.getBody() ).toBe( "test body" );
} );

it( "can seed and clear a loaded relationship", function() {
var user = getInstance( "User" ).findOrFail( 1 );
var seededPost = getInstance( "Post" ).findOrFail( 1245 );
variables.queries = [];

user.assignRelationship( "posts", [ seededPost ] );

expect( user.isRelationshipLoaded( "posts" ) ).toBeTrue();
expect( user.getPosts() ).toHaveLength( 1 );
expect( user.getPosts()[ 1 ].keyValues() ).toBe( seededPost.keyValues() );
expect( variables.queries ).toBeEmpty();

user.clearRelationship( "posts" );
expect( user.isRelationshipLoaded( "posts" ) ).toBeFalse();
expect( user.getPosts() ).toHaveLength( 2 );
expect( variables.queries ).toHaveLength( 1 );
} );

it( "can call exists methods on a relationship class", () => {
var elpete = getInstance( "User" ).findOrFail( 1 );
expect( elpete.favoritePost().exists() ).toBeTrue();
Expand Down
Loading