hooks

Hooks

Just like ActiveRecord in Rails, RestMod lets you modify a model's behavior using a wide range of hooks. The hooks are placed on the model's lifecycle key points.

1. Hooks that apply to every record and collection of a given Model

This is the most ActiveRecord'ish approach

var Bike = $restmod.model('/bikes', {
  $hooks: {
      'before-save': function() {
        this.partCount = this.parts.length;
      }
    }
});
2. Hooks that apply only to a particular record

It's also possible to modify only a single record's (model instance) behavior.

var bike = Bike.$new();
bike.$on('before-save', function() {
  this.partCount = this.parts.length;
});
3. Hooks that apply only to a certain collection and its records

You can catch collection related events by attaching hooks directly to a collection:

var bikes = Bike.$collection();
bikes.$on('after-fetch-many', function() {
  this.redBikesCount = this.countBikes({color:'red'});
});
bikes.$fetch(); // this call will trigger the hook defined above

Note that Hooks that are defined at the collection level will also catch the contained record's events.

var bikes = Bike.$collection();
bikes.$on('before-save', function() {
  this.partCount = this.parts.length;
});
bike = bikes.$new();
bike.$save(); // this call will trigger the hook defined above
4. Hooks that apply to a relation object

The hasMany and hasOne relations support hooks, these can be defined in the relation definition or in the type config block

In the relation definition:

var Bike = $restmod.model('/bikes'.$mix({
    parts: {
        hasMany: 'Part',
        hooks: {
            'after-fetch-many': function() { /* do something with the new parts */ }
        }
    }
});

or in the configuration block (applies to every relation where the extended class is the NESTED resource):

Var Part = $restmod.model().$mix({
    $config {
        hasMany: {
            hooks: {
                'after-has-many-init': function() {
                    // Here we are using the init hook to override every hasMany Part relation scope.
                    // This can be useful if a custom url scheme is needed for relations.
                    this.$scope = customScope(this.$scope);
                }
            }
        }
    }
})

To access the owner object inside a relation hook, use the child object's $owner property:

var Bike = $restmod.model('/bikes').$mix({
    parts: {
        hasMany: 'Part',
        hooks: {
            'after-fetch-many': function() {
                this.$owner.partsCount = this.length; // update the owner partCount every time the relation is fetched!
            }
        }
    }
});

Both hasOne and hasMany trigger an special event after hooks are added to the child resource, this enables you to specify some logic to be run after relation resource is initialized (since hooks are added AFTER after-init and after-collection-init are triggered). hasMany triggers after-has-many-init after after-collection-init. hasOne triggers after-has-one-init after after-init.

5. Hooks that apply only to a certain execution context using $decorate, used mainly to modify a method behaviour
var Bike = $restmod.model('/bikes', {
    // Modify $fetch so it uses POST instead of GET:
    $fetchWithPost: function(_params) {
        return this.$decorate({
          'before-request': function(_req) {
        _req.method = 'POST';
        _req.data = _params;
            }
        }, function() {
            // every method from same context called inside this function will be decorated.
            return this.$fetch();
        });
    }
});

Object lifecycle

When calling $new to generate a new record:

Event's name parameters 'this' refers to notes
after-init record

For $fetch on a record:

Event's name parameters 'this' refers to notes
before-fetch http-request record
before-request http-request record
after-request[-error] http-response record
after-feed raw record data record (only called if no errors)
after-fetch[-error] http-response record

For $fetch on a collection:

Event's name parameters 'this' refers to notes
before-fetch-many http-request collection
before-request http-request collection
after-request[-error] http-response collection
after-feed raw collection data collection (only called if no errors)
after-fetch-many[-error] http-response collection

For $save when record is new (creating):

Event's name parameters 'this' refers to notes
before-render serialized record record allows modifiying serialized record data before is sent to server
before-save http-request record
before-create http-request record
before-request http-request record only called if no errors
after-request[-error] http-response record
after-feed serialized record record only called if no errors and if server returned data
after-add record collection only called if record belongs to a collection and has not been revealed yet
after-create[-error] http-response record
after-save[-error] http-response record

For $save when record is not new (updating):

Event's name parameters 'this' refers to notes
before-render serialized record record allows modifiying serialized record data before is sent to server
before-save http-request record
before-update http-request record
before-request http-request record only called if no errors
after-request[-error] http-response record
after-feed serialized record record only called if no errors and if server returned data
after-update[-error] http-response record
after-save[-error] http-response record

For $destroy:

Event's name parameters 'this' refers to notes
before-destroy http-request record
before-request http-request record
after-request[-error] http-response record
after-remove record collection only called if record belongs to a collection
after-destroy[-error] http-response record

Notes: The before-request hooks can be used to modify the request before is sent. The after-request[-error] hooks can be used to modify the request before processed by model.

Defining custom events

Additional events can be triggered by user defined methods using the $dispatch method