quick icon indicating copy to clipboard operation
quick copied to clipboard

.create() can't set non-persistent values

Open DiscountDarcy opened this issue 4 years ago • 5 comments

If we define a property as non-persistent and then try to create an entity with .create() that sets that property, Quick will throw an error that it doesn't exist.

Any particular reason we shouldn't be able to set non-persistent values when creating an entity?

DiscountDarcy avatar Aug 23 '21 15:08 DiscountDarcy

A non-persistent property is ignored completely by Quick. When using create or fill, Quick only looks at attributes which is the Quick term for properties it knows and cares about.

You could use insert and update flags on the property to prevent writes, if that is what you are after. (https://quick.ortusbooks.com/guide/getting-started/defining-an-entity#insert-and-update) But if this value never comes from the database, you may want to set it before calling create.

elpete avatar Aug 23 '21 15:08 elpete

The scenario is that we have an attribute which governs whether certain lifecycle events fire. It never comes from the database.

We can't set it before calling create because it's created via the relationship of a related entity, e.g.

user.posts().create({})

DiscountDarcy avatar Aug 23 '21 15:08 DiscountDarcy

What about adding a custom create method for that entity?

public any function create( struct attributes = {}, boolean ignoreNonExistentAttributes = false ) {
    var entity = newEntity();
    entity.setLifecycleEventVar( arguments.attributes.lifecycleEventVar ?: "default" );
    structDelete( arguments.attributes, "lifecycleEventVar" );
    entity.fill( arguments.attributes, arguments.ignoreNonExistentAttributes );
    return entity.save();
}

Or what I like to think of as a "named constructor":

public any function createWithLifecycle(
    required string lifecycleEventVar,
    struct attributes = {},
    boolean ignoreNonExistentAttributes = false
) {
    var entity = newEntity();
    entity.setLifecycleEventVar( arguments.lifecycleEventVar );
    entity.fill( arguments.attributes, arguments.ignoreNonExistentAttributes );
    return entity.save();
}

Would one of those work?

elpete avatar Aug 23 '21 19:08 elpete

Sure, but why does .create() need to be particular about setting the attributes as it is now? From the standpoint of 'I want to create this entity,' I don't care whether field A or field B is persistent or not; I'm hydrating an entity. It's not a non-existent attribute, it's just not a persistent attribute.

I can come up with a workaround but it's not obvious to me that one should be required.

DiscountDarcy avatar Aug 23 '21 19:08 DiscountDarcy

Hmmm....I'm not sure. fill definitely does a lot more than just call setters. But if that is added and the tests pass I have no problems with it.

elpete avatar Aug 23 '21 19:08 elpete