src/module/extended/builder-ext.js
'use strict';
RMModule.factory('RMBuilderExt', ['$injector', '$parse', 'inflector', '$log', 'restmod', function($injector, $parse, inflector, $log, restmod) {
var bind = angular.bind,
isFunction = angular.isFunction;
/**
* @class ExtendedBuilderApi
*
* @description
*
* Non-core builder extensions
*
* Adds the following property modifiers:
* * `serialize` sets the encoder and decoder beaviour for an attribute, maps to {@link BuilderApi#attrSerializer}
*
*/
var EXT = {
/**
* @memberof ExtendedBuilderApi#
*
* @description Sets an url prefix to be added to every url generated by the model.
*
* This applies even to objects generated by the `$single` method.
*
* This method is intended to be used in a base model mixin so everymodel that extends from it
* gets the same url prefix.
*
* Usage:
*
* ```javascript
* var BaseModel = restmod.mixin(function() {
* this.setUrlPrefix('/api');
* })
*
* var bike = restmod.model('/bikes', BaseModel).$build({ id: 1 });
* console.log(bike.$url()) // outputs '/api/bikes/1'
* ```
*
* @param {string} _prefix url portion
* @return {BuilderApi} self
*/
setUrlPrefix: function(_prefix) {
return this.setProperty('urlPrefix', _prefix);
},
/**
* @memberof ExtendedBuilderApi#
*
* @description Changes the model's primary key.
*
* Primary keys are passed to scope's url methods to generate urls. The default primary key is 'id'.
*
* **ATTENTION** Primary keys are extracted from raw data, so _key must use raw api naming.
*
* @param {string|function} _key New primary key.
* @return {BuilderApi} self
*/
setPrimaryKey: function(_key) {
return this.setProperty('primaryKey', _key);
},
/**
* @memberof ExtendedBuilderApi#
*
* @description Assigns a serializer to a given attribute.
*
* A _serializer is:
* * an object that defines both a `decode` and a `encode` method
* * a function that when called returns an object that matches the above description.
* * a string that represents an injectable that matches any of the above descriptions.
*
* @param {string} _name Attribute name
* @param {string|object|function} _serializer The serializer
* @return {BuilderApi} self
*/
attrSerializer: function(_name, _serializer, _opt) {
if(typeof _serializer === 'string') {
_serializer = $injector.get(inflector.camelize(_serializer, true) + 'Serializer');
}
if(isFunction(_serializer)) _serializer = _serializer(_opt);
if(_serializer.decode) this.attrDecoder(_name, bind(_serializer, _serializer.decode));
if(_serializer.encode) this.attrEncoder(_name, bind(_serializer, _serializer.encode));
return this;
},
/// Experimental modifiers
/**
* @memberof ExtendedBuilderApi#
*
* @description Expression attributes are evaluated every time new data is fed to the model.
*
* @param {string} _name Attribute name
* @param {string} _expr Angular expression to evaluate
* @return {BuilderApi} self
*/
attrExpression: function(_name, _expr) {
var filter = $parse(_expr);
return this.on('after-feed', function() {
this[_name] = filter(this);
});
}
};
return restmod.mixin(function() {
this.extend('setUrlPrefix', EXT.setUrlPrefix)
.extend('setPrimaryKey', EXT.setPrimaryKey)
.extend('attrSerializer', EXT.attrSerializer, ['serialize']);
});
}]);