Model Lifecycle

Operations on instances move data through a lifecycle. JSData allows you define functions to be executed at various points in this process. This affords you the opportunity to modify data as it flows through the lifecycle or abort the lifecycle if necessary.

These model hooks have the following signature:

// resource - The object returned by DS#defineResource
// data - The data moving through the lifecycle.
//        You must pass the data through to the next part of the lifecycle
// cb - Optional callback function. 
//      Use it Node-style or ignore it and return a promise.
//      Lifecycle hooks for synchronous methods do not take a callback.
asyncLifecycleHook(resource, data, cb) {
  // abort
  cb(new Error('reason'));
     
  // or continue the lifecycle
  cb(null, data);
  
  // or return a promise instead of executing the callback
  return new Promise(function (resolve, reject) {
    resolve(attrs);
  });
}

syncLifecycleHook(resource, data) {
  // do something
  // can't affect the flow
}

Lifecycle hooks can be defined globally or per-resource or overridden during a method call:

// using the "afterCreate" as an example

var store = new DS({
  // set a default lifecycle hook
  afterCreate: function (...) {...}
});
  
var User = store.defineResource({
  name: 'user',
  // override the hook for this resource
  afterCreate: function (...) {...}
});

User.create({
  name: 'john'
}, {
  // override the hook just for this method call
  afterCreate: function(...) {...}
}).then(...)

The hooks' second argument is an object or an array of objects, depending on if the operation was triggered on a single item or a collection of items.

The following methods move through a lifecycle:

DS#create

These can be used to affect data as it flows or abort the lifecycle.

  • beforeValidate(resource, attrs[, cb])
  • validate(resource, attrs[, cb])
  • afterValidate(resource, attrs[, cb])
  • beforeCreate(resource, attrs[, cb])
  • afterCreate(resource, attrs[, cb])
DS#save & DS#update & DS#updateAll

These can be used to affect data as it flows or abort the lifecycle.

  • beforeValidate(resource, attrs|arrayOfAttrs[, cb])
  • validate(resource, attrs|arrayOfAttrs[, cb])
  • afterValidate(resource, attrs|arrayOfAttrs[, cb])
  • beforeUpdate(resource, attrs|arrayOfAttrs[, cb])
  • afterUpdate(resource, attrs|arrayOfAttrs[, cb])

DS#destroy && DS#destroyAll

These can be used to affect data as it flows or abort the lifecycle.

  • beforeDestroy(resource, attrs|arrayOfAttrs[, cb])
  • afterDestroy(resource, attrs|arrayOfAttrs[, cb])

DS#find

These can be used to affect data as it flows or abort the lifecycle.

  • afterFind(resource, attrs[, cb])

DS#findAll

These can be used to affect data as it flows or abort the lifecycle.

  • afterFindAll(resource, attrs[, cb])

DS#loadRelations

These can be used to affect data as it flows or abort the lifecycle.

  • afterLoadRelations(resource, attrs[, cb])

The following methods are available as hooks in the lifecycle, but can't affect it:

DS#inject

These cannot be used to abort the lifecycle. You can only modify the instance or array of instances that are passed in–you can't return new ones. No return value, no callback. Called after create, update, save, find, findAll and loadRelations when cacheResponse is true.

  • beforeInject(resource, instances|arrayOfInstances)
  • afterInject(resource, instances|arrayOfInstances)

DS#eject & DS#ejectAll

These cannot be used to abort the lifecycle. You can only modify the instance or array of instances that are passed in–you can't return new ones. No return value, no callback.

  • beforeEject(resource, instances|arrayOfInstances)
  • afterEject(resource, instances|arrayOfInstances)

DS#createInstance

These cannot be used to abort the lifecycle. You can only modify the instance that is passed in–you can't return a new one. No return value, no callback.

  • beforeCreateInstance(resource, attrs)
  • afterCreateInstance(resource, instance)

DS#reap

These cannot be used to abort the lifecycle. You can only modify the attrs that are passed in–no reassignment. No return value, no callback.

  • beforeReap(resource, arrayOfAttrs)
  • afterReap(resource, arrayOfAttrs)

See the DS#defaults for more details.

Additional reading:

📘

Need help?

Want more examples or have a question? Post on the Slack channel or mailing list then we'll get your question answered and probably update this wiki.