diff --git a/CHANGELOG.md b/CHANGELOG.md
index a093285..8f82caf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+
+### 1.1.6 (2015-01-06)
+
+
+#### Bug Fixes
+
+* adds package.json to release task ([f7875766](http://github.com/angular-platanus/restmod/commit/f78757663c5b64136886f67069f7d694669607a1))
+* **factory:** fixes typo in call to canonicalUrlFor. ([5bfa439a](http://github.com/angular-platanus/restmod/commit/5bfa439a1cfe853d322403516ea70e12d51389fa), closes [#227](http://github.com/angular-platanus/restmod/issues/227))
+* **fastq:** adds missing 'catch' method to promises ([1fea426a](http://github.com/angular-platanus/restmod/commit/1fea426a1c6607ec3cc323d560f205a7e615be9f), closes [#183](http://github.com/angular-platanus/restmod/issues/183))
+
+
+#### Features
+
+* **nesteddirty:** adds NestedDirtyModel plugin ([04b6178f](http://github.com/angular-platanus/restmod/commit/04b6178fcd99cd06e08845676313443f290c059e))
+* **plugin.nested_dirty:**
+ * specifies how changing a nested object property to another type affects changed ([2a295779](http://github.com/angular-platanus/restmod/commit/2a295779d77e94300e7aea6a4072c638179fc888))
+ * adds support for properties ([94bf9375](http://github.com/angular-platanus/restmod/commit/94bf937592136425bad514f618532af248a13936))
+* **service:** adds support for custom relation url name transformation. ([5a080925](http://github.com/angular-platanus/restmod/commit/5a08092513b8d1713b7431ea243ecc66564c238d), closes [#159](http://github.com/angular-platanus/restmod/issues/159))
+
+
### 1.1.5 (2014-12-10)
diff --git a/bower.json b/bower.json
index 9d54bb4..57df73f 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "angular-restmod",
- "version": "1.1.5",
+ "version": "1.1.6",
"authors": [
"Ignacio Baixas "
],
diff --git a/dist/angular-restmod-bundle.js b/dist/angular-restmod-bundle.js
index ba7a0e0..d748a2f 100644
--- a/dist/angular-restmod-bundle.js
+++ b/dist/angular-restmod-bundle.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -687,8 +687,8 @@ RMModule.factory('RMCommonApi', ['$http', 'RMFastQ', '$log', function($http, $q,
if(_for) {
_for = '$' + _for + 'UrlFor';
if(this.$scope[_for]) return this.$scope[_for](this);
- } else if(this.$scope.$cannonicalUrlFor) {
- return this.$scope.$cannonicalUrlFor(this);
+ } else if(this.$scope.$canonicalUrlFor) {
+ return this.$scope.$canonicalUrlFor(this);
}
return this.$scope.$urlFor(this);
@@ -2394,7 +2394,7 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
}
}
- var scope = this.$buildScope(_model, _url || inflector.parameterize(_attr)), col; // TODO: name to url transformation should be a Model strategy
+ var scope = this.$buildScope(_model, _url || _model.encodeUrlName(_attr)), col;
// setup collection
col = _model.$collection(_params || null, scope);
@@ -2459,7 +2459,7 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
}
}
- var scope = this.$buildScope(_model, _url || inflector.parameterize(_attr)), inst;
+ var scope = this.$buildScope(_model, _url || _model.encodeUrlName(_attr)), inst;
// setup record
inst = _model.$new(null, scope);
@@ -2689,8 +2689,8 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
});
}]);
-RMModule.factory('RMModelFactory', ['$injector', 'inflector', 'RMUtils', 'RMScopeApi', 'RMCommonApi', 'RMRecordApi', 'RMListApi', 'RMCollectionApi', 'RMExtendedApi', 'RMSerializer', 'RMBuilder',
- function($injector, inflector, Utils, ScopeApi, CommonApi, RecordApi, ListApi, CollectionApi, ExtendedApi, Serializer, Builder) {
+RMModule.factory('RMModelFactory', ['$injector', '$log', 'inflector', 'RMUtils', 'RMScopeApi', 'RMCommonApi', 'RMRecordApi', 'RMListApi', 'RMCollectionApi', 'RMExtendedApi', 'RMSerializer', 'RMBuilder',
+ function($injector, $log, inflector, Utils, ScopeApi, CommonApi, RecordApi, ListApi, CollectionApi, ExtendedApi, Serializer, Builder) {
var NAME_RGX = /(.*?)([^\/]+)\/?$/,
extend = Utils.extendOverriden;
@@ -3023,7 +3023,25 @@ RMModule.factory('RMModelFactory', ['$injector', 'inflector', 'RMUtils', 'RMScop
* @params {string} _name Record name
* @return {string} Response (raw) name
*/
- encodeName: null
+ encodeName: null,
+
+ /**
+ * @memberof StaticApi#
+ *
+ * @description The model name to url encoding strategy
+ *
+ * This method is called when translating a name into an url fragment (mainly by relations).
+ *
+ * By default it uses the `inflector.parameterize` method, in 1.2 this will change and the default
+ * behaviour will be to do nothing.
+ *
+ * @params {string} _name local name
+ * @return {string} url fragment
+ */
+ encodeUrlName: function(_name) {
+ $log.warn('Default paremeterization of urls will be disabled in 1.2, override Model.encodeUrlName with inflector.parameterize in your base model to keep the same behaviour.');
+ return inflector.parameterize(_name);
+ }
}, ScopeApi);
@@ -3302,7 +3320,10 @@ RMModule.factory('RMModelFactory', ['$injector', 'inflector', 'RMUtils', 'RMScop
*/
RMModule.factory('RMFastQ', [function() {
- var isFunction = angular.isFunction;
+ var isFunction = angular.isFunction,
+ catchError = function(_error) {
+ return this.then(null, _error);
+ };
function simpleQ(_val, _withError) {
@@ -3314,6 +3335,7 @@ RMModule.factory('RMFastQ', [function() {
then: function(_success, _error) {
return simpleQ(_withError ? _error(_val) : _success(_val));
},
+ 'catch': catchError,
'finally': function(_cb) {
var result = _cb();
if(result && isFunction(_val.then)) {
@@ -3347,6 +3369,7 @@ RMModule.factory('RMFastQ', [function() {
simple.then(_success, _error) :
wrappedQ(_promise.then(_success, _error));
},
+ 'catch': catchError,
'finally': function(_cb) {
return simple ?
simple['finally'](_cb) :
diff --git a/dist/angular-restmod-bundle.min.js b/dist/angular-restmod-bundle.min.js
index 46330b4..6000fbd 100644
--- a/dist/angular-restmod-bundle.min.js
+++ b/dist/angular-restmod-bundle.min.js
@@ -1,8 +1,8 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-!function(a,b){"use strict";!function(a){a.module("platanus.inflector",[]).provider("inflector",[function(){function a(a,b,c){if(-1===c.indexOf(a.toLowerCase()))for(var d,e=0;d=b[e++];)if(a.match(d[0]))return a.replace(d[0],d[1]);return a}var b="en",c={en:{uncountable:["music","art","love","happiness","advice","furniture","luggage","sugar","butter","water","electricity","gas","power","currency","equipment","information","rice","money","species","series","fish","sheep","moose","deer","news"],plural:[[new RegExp("(m)an$","gi"),"$1en"],[new RegExp("(pe)rson$","gi"),"$1ople"],[new RegExp("(child)$","gi"),"$1ren"],[new RegExp("^(ox)$","gi"),"$1en"],[new RegExp("(ax|test)is$","gi"),"$1es"],[new RegExp("(octop|vir)us$","gi"),"$1i"],[new RegExp("(alias|status)$","gi"),"$1es"],[new RegExp("(bu)s$","gi"),"$1ses"],[new RegExp("(buffal|tomat|potat)o$","gi"),"$1oes"],[new RegExp("([ti])um$","gi"),"$1a"],[new RegExp("sis$","gi"),"ses"],[new RegExp("(?:([^f])fe|([lr])f)$","gi"),"$1$2ves"],[new RegExp("(hive)$","gi"),"$1s"],[new RegExp("([^aeiouy]|qu)y$","gi"),"$1ies"],[new RegExp("(x|ch|ss|sh)$","gi"),"$1es"],[new RegExp("(matr|vert|ind)ix|ex$","gi"),"$1ices"],[new RegExp("([m|l])ouse$","gi"),"$1ice"],[new RegExp("(quiz)$","gi"),"$1zes"],[new RegExp("s$","gi"),"s"],[new RegExp("$","gi"),"s"]],singular:[[new RegExp("(m)en$","gi"),"$1an"],[new RegExp("(pe)ople$","gi"),"$1rson"],[new RegExp("(child)ren$","gi"),"$1"],[new RegExp("([ti])a$","gi"),"$1um"],[new RegExp("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$","gi"),"$1$2sis"],[new RegExp("(hive)s$","gi"),"$1"],[new RegExp("(tive)s$","gi"),"$1"],[new RegExp("(curve)s$","gi"),"$1"],[new RegExp("([lr])ves$","gi"),"$1f"],[new RegExp("([^fo])ves$","gi"),"$1fe"],[new RegExp("([^aeiouy]|qu)ies$","gi"),"$1y"],[new RegExp("(s)eries$","gi"),"$1eries"],[new RegExp("(m)ovies$","gi"),"$1ovie"],[new RegExp("(x|ch|ss|sh)es$","gi"),"$1"],[new RegExp("([m|l])ice$","gi"),"$1ouse"],[new RegExp("(bus)es$","gi"),"$1"],[new RegExp("(o)es$","gi"),"$1"],[new RegExp("(shoe)s$","gi"),"$1"],[new RegExp("(cris|ax|test)es$","gi"),"$1is"],[new RegExp("(octop|vir)i$","gi"),"$1us"],[new RegExp("(alias|status)es$","gi"),"$1"],[new RegExp("^(ox)en","gi"),"$1"],[new RegExp("(vert|ind)ices$","gi"),"$1ex"],[new RegExp("(matr)ices$","gi"),"$1ix"],[new RegExp("(quiz)zes$","gi"),"$1"],[new RegExp("s$","gi"),""]]}};return{registerLocale:function(a,b){c[a]=b},setLocale:function(a){b=a},$get:["$log",function(d){function e(a){a=a||b;var e=c[a];return e||d.warn("Invalid inflector locale "+a),e}return{camelize:function(a,b){return"string"!=typeof a?a:a.replace(/(?:^[-_\s]*|[-_\s]+)([A-Z\d])/gi,function(a,c,d){return b||0!==d?c.toUpperCase():c})},parameterize:function(a,b){return"string"!=typeof a?a:a.replace(/(?:[A-Z]+|[0-9]+)/g,function(a,c){return 0===c?a:(b||"-")+a}).toLowerCase()},dasherize:function(a,b){return a.replace(/[-_\s]+/g,b||"-")},singularize:function(b,c){var d=e(c);return d?a(b,d.singular,d.uncountable):b},pluralize:function(b,c){var d=e(c);return d?a(b,d.plural,d.uncountable):b}}}]}}])}(a);var c=a.module("restmod",["ng","platanus.inflector"]);c.provider("restmod",[function(){function b(a){return function(b){b.invoke(a,this,{$builder:this})}}var c=["RMBuilderExt","RMBuilderRelations","RMBuilderComputed"];return{rebase:function(){var d,e,f=arguments.length;for(e=0;f>e;e++)d=arguments[e],(a.isArray(d)||a.isFunction(d))&&(d=b(d)),c.push(d);return this},$get:["RMModelFactory","$log",function(a,b){var d=Array.prototype.slice,e={model:function(e){var f=a(e,c);return arguments.length>1&&(f.mix(d.call(arguments,1)),b.warn("Passing mixins and difinitions in the model method will be deprecated in restmod 1.2, use restmod.model().mix() instead.")),f},mixin:function(){return{$isAbstract:!0,$$chain:d.call(arguments,0)}},singleton:function(a){return e.model.apply(this,arguments).single(a)}};return e}]}}]).factory("model",["restmod",function(a){return a.model}]).factory("mixin",["restmod",function(a){return a.mixin}]),c.factory("RMCollectionApi",["RMUtils",function(c){var d=a.extend;return{$isCollection:!0,$initialize:function(){this.$dispatch("after-collection-init")},$decode:function(b,d){c.assert(b&&a.isArray(b),"Collection $decode expected array");for(var e=0,f=b.length;f>e;e++)this.$buildRaw(b[e],d).$reveal();return this.$dispatch("after-feed-many",[b]),this},$encode:function(a){for(var b=[],c=0,d=this.length;d>c;c++)b.push(this[c].$encode(a));return this.$dispatch("before-render-many",[b]),b},$clear:function(){return this.$always(function(){this.length=0})},$fetch:function(a){return this.$action(function(){var b={method:"GET",url:this.$url("fetchMany"),params:this.$params};a&&(b.params=b.params?d(b.params,a):a),this.$dispatch("before-fetch-many",[b]).$send(b,function(a){this.$unwrap(a.data).$dispatch("after-fetch-many",[a])},function(a){this.$dispatch("after-fetch-many-error",[a])})})},$add:function(a,d){return c.assert(a.$type&&a.$type===this.$type,"Collection $add expects record of the same $type"),this.$action(function(){a.$position===b&&(d!==b?this.splice(d,0,a):this.push(a),a.$position=!0,this.$dispatch("after-add",[a]))})},$remove:function(a){return this.$action(function(){var c=this.$indexOf(a);-1!==c&&(this.splice(c,1),a.$position=b,this.$dispatch("after-remove",[a]))})},$indexOf:function(a){for(var b="function"==typeof a?a:!1,c=0,d=this.length;d>c;c++)if(b?b(this[c]):this[c]===a)return c;return-1}}}]),c.factory("RMCommonApi",["$http","RMFastQ","$log",function(c,d,e){function f(a,c){var d=a.$dispatcher();return function(e){var f=a.$promise;a.$promise=b;try{a.$last=e;var g=d?a.$decorate(d,c,[a]):c.call(a,a);return g===b?a.$promise:g}finally{a.$promise=f}}}var g=[],h={$url:function(a){if(a){if(a="$"+a+"UrlFor",this.$scope[a])return this.$scope[a](this)}else if(this.$scope.$cannonicalUrlFor)return this.$scope.$cannonicalUrlFor(this);return this.$scope.$urlFor(this)},$dispatch:function(a,c,d){var e,f,h,i=this.$$dsp;if(d||(d=this),i&&(this.$$dsp=b,i(a,c,d)),this.$$cb&&(e=this.$$cb[a]))for(f=0;h=e[f];f++)h.apply(d,c||g);return this.$scope&&this.$scope.$dispatch?this.$scope.$dispatch(a,c,d):this.$type&&this.$type.$dispatch(a,c,d),this.$$dsp=i,this},$on:function(a,b){var c=(this.$$cb||(this.$$cb={}))[a]||(this.$$cb[a]=[]);return c.push(b),this},$decorate:function(a,b,c){var d=this.$$dsp;this.$$dsp="function"!=typeof a&&a?function(b,c,e){d&&d.apply(null,arguments);var f=a[b];f&&f.apply(e,c||g)}:a;try{return b.apply(this,c)}finally{this.$$dsp=d}},$dispatcher:function(){return this.$$dsp},$asPromise:function(){var a=this;return this.$promise?this.$promise.then(function(){return a},function(){return d.reject(a)}):d.when(this)},$then:function(a,b){return this.$promise=this.$promise?this.$promise.then(a?f(this,a):a,b?f(this,b):b):d.when(f(this,a)(this)),this},$always:function(a){return this.$then(a,a)},$finally:function(a){return this.$promise=this.$promise["finally"](f(this,a)),this},$send:function(a,b,g){this.$type.getProperty("style")||e.warn("No API style base was selected, see the Api Integration FAQ for more information on this warning");var h=this.$$action;return this.$always(function(){return this.$response=null,this.$status="pending",this.$dispatch("before-request",[a]),c(a).then(f(this,function(){h&&h.canceled?this.$status="canceled":(this.$status="ok",this.$response=this.$last,this.$dispatch("after-request",[this.$last]),b&&b.call(this,this.$last))}),f(this,function(){return h&&h.canceled?void(this.$status="canceled"):(this.$status="error",this.$response=this.$last,this.$dispatch("after-request-error",[this.$last]),g&&g.call(this,this.$last),d.reject(this))}))})},$action:function(a){var b={canceled:!1},c=this.$pending||(this.$pending=[]);return c.push(b),this.$always(function(){var c=this.$$action;try{return b.canceled?d.reject(this):(this.$$action=b,a.call(this))}finally{this.$$action=c}}).$finally(function(){c.splice(c.indexOf(b),1)})},$cancel:function(){return this.$pending&&a.forEach(this.$pending,function(a){a.canceled=!0}),this},$hasPendingActions:function(){var b=0;return this.$pending&&a.forEach(this.$pending,function(a){a.canceled||b++}),b>0}};return h}]),c.factory("RMExtendedApi",["$q","RMPackerCache",function(a,b){return{$decode:function(a,b){return this.$resolved===!1&&this.$clear&&this.$clear(),this.$super(a,b),this.$resolved=!0,this},$unwrap:function(a,c){try{return b.prepare(),a=this.$type.unpack(this,a),this.$decode(a,c)}finally{b.clear()}},$wrap:function(a){var b=this.$encode(a);return b=this.$type.pack(this,b)},$reset:function(){return this.$cancel().$action(function(){this.$resolved=!1})},$resolve:function(a){return this.$action(function(){this.$dispatch("before-resolve",[]),this.$resolved||this.$fetch(a)})},$refresh:function(a){return this.$reset().$fetch(a)}}}]),c.factory("RMListApi",[function(){return{$asList:function(a){var b=this.$type.list(),c=this.$asPromise();return b.$promise=c.then(function(c){b.push.apply(b,a?a(c):c)}),b}}}]),c.factory("RMRecordApi",["RMUtils",function(a){var c=function(b,c,d){this.$scope=b,this.$target=c,this.$partial=a.cleanUrl(d)};return c.prototype={$nestedUrl:function(){return a.joinUrl(this.$scope.$url(),this.$partial)},$urlFor:function(a){return a.$isCollection||this.$target.isNested()?this.$nestedUrl():this.$target.$urlFor(a)},$fetchUrlFor:function(){return this.$nestedUrl()},$createUrlFor:function(){return null}},{$initialize:function(){this.$super(),this.$dispatch("after-init")},$buildUrl:function(c){return this.$pk===b||null===this.$pk?null:a.joinUrl(c.$url(),this.$pk+"")},$buildScope:function(a,b){return a.$buildOwnScope?void 0:new c(this,a,b)},$each:function(a,b){for(var c in this)this.hasOwnProperty(c)&&"$"!==c[0]&&a.call(b||this[c],this[c],c);return this},$decode:function(c,d){return this.$type.decode(this,c,d||a.READ_MASK),(this.$pk===b||null===this.$pk)&&(this.$pk=this.$type.inferKey(c)),this.$dispatch("after-feed",[c]),this},$encode:function(b){var c=this.$type.encode(this,b||a.CREATE_MASK);return this.$dispatch("before-render",[c]),c},$fetch:function(b){return this.$action(function(){var c=this.$url("fetch");a.assert(!!c,"Cant $fetch if resource is not bound");var d={method:"GET",url:c,params:b};this.$dispatch("before-fetch",[d]),this.$send(d,function(a){this.$unwrap(a.data),this.$dispatch("after-fetch",[a])},function(a){this.$dispatch("after-fetch-error",[a])})})},$extend:function(a){return this.$action(function(){for(var b in a)a.hasOwnProperty(b)&&"$"!==b[0]&&(this[b]=a[b])})},$update:function(a){return this.$extend(a).$save()},$save:function(c){return this.$action(function(){var d,e=this.$url("update");e?(d=c?{method:this.$type.getProperty("patchMethod","PATCH"),url:e,data:this.$wrap(function(a){for(var b=0,d=c.length;d>b;b++)if(a===c[b]||0===a.indexOf(c[b]+".")||0===c[b].indexOf(a+"."))return!1;return!0})}:{method:"PUT",url:e,data:this.$wrap(a.UPDATE_MASK)},this.$dispatch("before-update",[d,!!c]).$dispatch("before-save",[d]).$send(d,function(a){this.$unwrap(a.data).$dispatch("after-update",[a,!!c]).$dispatch("after-save",[a])},function(a){this.$dispatch("after-update-error",[a,!!c]).$dispatch("after-save-error",[a])})):(e=this.$url("create")||this.$scope.$url(),a.assert(!!e,"Cant $create if parent scope is not bound"),d={method:"POST",url:e,data:this.$wrap(a.CREATE_MASK)},this.$dispatch("before-save",[d]).$dispatch("before-create",[d]).$send(d,function(a){this.$unwrap(a.data),this.$scope.$isCollection&&this.$position===b&&!this.$preventReveal&&this.$scope.$add(this,this.$revealAt),this.$dispatch("after-create",[a]).$dispatch("after-save",[a])},function(a){this.$dispatch("after-create-error",[a]).$dispatch("after-save-error",[a])}))})},$destroy:function(){return this.$action(function(){var a=this.$url("destroy");if(a){var b={method:"DELETE",url:a};this.$dispatch("before-destroy",[b]).$send(b,function(a){this.$scope.$remove&&this.$scope.$remove(this),this.$dispatch("after-destroy",[a])},function(a){this.$dispatch("after-destroy-error",[a])})}else this.$scope.$remove&&this.$scope.$remove(this)})},$moveTo:function(a){return this.$position!==b||(this.$revealAt=a),this},$reveal:function(a){return a===b||a?this.$scope.$add(this,this.$revealAt):this.$preventReveal=!0,this}}}]),c.factory("RMScopeApi",["RMUtils",function(){return{$urlFor:function(a){var b=this.$type.isNested()?this:this.$type;return"function"==typeof a.$buildUrl?a.$buildUrl(b):b.$url()},$new:function(a,b){return this.$super(a,b)},$build:function(a){return this.$new().$extend(a)},$buildRaw:function(a,b){var c=this.$new(this.$type.inferKey(a));return c.$decode(a,b),c},$find:function(a,b){return this.$new(a).$resolve(b)},$create:function(a){return this.$build(a).$save()},$collection:function(a,b){return this.$super(a,b)},$search:function(a){return this.$collection(a).$fetch()}}}]),c.factory("RMBuilder",["$injector","inflector","$log","RMUtils",function(b,c,d,e){function f(a){var b={init:["attrDefault"],mask:["attrMask"],ignore:["attrMask"],map:["attrMap","force"],decode:["attrDecoder","param","chain"],encode:["attrEncoder","param","chain"],"volatile":["attrVolatile"]};this.dsl=k(a,{describe:function(a){return g(a,function(a,b){switch(b.charAt(0)){case"@":d.warn("Usage of @ in description objects will be removed in 1.2, use a $extend block instead"),this.define("Scope."+b.substring(1),a);break;case"~":b=c.parameterize(b.substring(1)),d.warn("Usage of ~ in description objects will be removed in 1.2, use a $hooks block instead"),this.on(b,a);break;default:if("$config"===b)for(var e in a)a.hasOwnProperty(e)&&this.setProperty(e,a[e]);else if("$extend"===b)for(var e in a)a.hasOwnProperty(e)&&this.define(e,a[e]);else if("$hooks"===b)for(var e in a)a.hasOwnProperty(e)&&this.on(e,a[e]);else l.test(b)?(d.warn("Usage of ~ in description objects will be removed in 1.2, use a $config block instead"),b=c.camelize(b.toLowerCase()),this.setProperty(b,a)):h(a)?this.attribute(b,a):j(a)?this.define(b,a):this.attrDefault(b,a)}},this),this},extend:function(a,c,d){return"string"==typeof a?(this[a]=e.override(this[name],c),d&&(b[d[0]]=d,d[0]=a)):e.extendOverriden(this,a),this},attribute:function(a,c){var d,e,f,g;for(d in c)if(c.hasOwnProperty(d)&&(e=b[d])){for(f=[a,c[d]],g=1;gb;b++)this.mixin(a[b])},mixin:function(a){a.$$chain?this.chain(a.$$chain):"string"==typeof a?this.mixin(b.get(a)):i(a)?this.chain(a):j(a)?a.call(this.dsl,b):this.dsl.describe(a)}},f}]),c.factory("RMBuilderComputed",["restmod",function(a){var b={attrAsComputed:function(a,b){return this.attrComputed(a,b),this}};return a.mixin(function(){this.extend("attrAsComputed",b.attrAsComputed,["computed"])})}]),c.factory("RMBuilderExt",["$injector","$parse","inflector","$log","restmod",function(b,c,d,e,f){var g=a.bind,h=a.isFunction,i={setUrlPrefix:function(a){return this.setProperty("urlPrefix",a)},setPrimaryKey:function(a){return this.setProperty("primaryKey",a)},attrSerializer:function(a,c,e){return"string"==typeof c&&(c=b.get(d.camelize(c,!0)+"Serializer")),h(c)&&(c=c(e)),c.decode&&this.attrDecoder(a,g(c,c.decode)),c.encode&&this.attrEncoder(a,g(c,c.encode)),this},attrExpression:function(a,b){var d=c(b);return this.on("after-feed",function(){this[a]=d(this)})}};return f.mixin(function(){this.extend("setUrlPrefix",i.setUrlPrefix).extend("setPrimaryKey",i.setPrimaryKey).extend("attrSerializer",i.attrSerializer,["serialize"])})}]),c.factory("RMBuilderRelations",["$injector","inflector","$log","RMUtils","restmod","RMPackerCache",function(a,c,d,e,f,g){function h(a,b){return function(){var c=this.$owner;this.$owner=b;try{return a.apply(this,arguments)}finally{this.$owner=c}}}function i(a,b,c){for(var d in b)b.hasOwnProperty(d)&&a.$on(d,h(b[d],c))}var j={attrAsCollection:function(b,f,g,h,j,k,l){var m,n;return this.attrDefault(b,function(){if("string"==typeof f&&(f=a.get(f),m=f.getProperty("hasMany",{}),n=m.hooks,j)){var e=f.$$getDescription(j);e&&"belongs_to"===e.relation||(d.warn("Must define an inverse belongsTo relation for inverseOf to work"),j=!1)}var h,o=this.$buildScope(f,g||c.parameterize(b));if(h=f.$collection(k||null,o),n&&i(h,n,this),l&&i(h,l,this),h.$dispatch("after-has-many-init"),j){var p=this;h.$on("after-add",function(a){a[j]=p})}return h}),(h||g)&&this.attrMap(b,h||g),this.attrDecoder(b,function(a){this[b].$reset().$decode(a)}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"has_many"}),this},attrAsResource:function(b,f,g,h,j,k){var l,m;return this.attrDefault(b,function(){if("string"==typeof f&&(f=a.get(f),l=f.getProperty("hasOne",{}),m=l.hooks,j)){var e=f.$$getDescription(j);e&&"belongs_to"===e.relation||(d.warn("Must define an inverse belongsTo relation for inverseOf to work"),j=!1)}var h,n=this.$buildScope(f,g||c.parameterize(b));return h=f.$new(null,n),m&&i(h,m,this),k&&i(h,k,this),h.$dispatch("after-has-one-init"),j&&(h[j]=this),h}),(h||g)&&this.attrMap(b,h||g),this.attrDecoder(b,function(a){this[b].$decode(a)}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"has_one"}),this},attrAsReference:function(c,d,f,h){function i(){"string"==typeof d&&(d=a.get(d))}return this.attrDefault(c,null).attrMask(c,e.WRITE_MASK).attrMeta(c,{relation:"belongs_to"}),this.attrDecoder(c,function(a){return null===a?null:(i(),void(this[c]&&this[c].$pk===d.inferKey(a)?this[c].$decode(a):this[c]=d.$buildRaw(a)))}),f!==!1&&this.attrMap(c+"Id",f||"*",!0).attrDecoder(c+"Id",function(a){a!==b&&(this[c]&&this[c].$pk===a||(null!==a&&a!==!1?(i(),this[c]=g.resolve(d.$new(a)),h&&this[c].$fetch()):this[c]=null))}).attrEncoder(c+"Id",function(){return this[c]?this[c].$pk:null}),this},attrAsReferenceToMany:function(b,d,f){function h(){"string"==typeof d&&(d=a.get(d))}function i(a,b){h(),b.length=0;for(var c=0,e=a.length;e>c;c++)b.push("object"==typeof a[c]?d.$buildRaw(a[c]):g.resolve(d.$new(a[c])))}if(this.attrDefault(b,function(){return[]}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"belongs_to_many"}),this.attrDecoder(b,function(a){a&&i(a,this[b])}),f!==!1){var j=c.singularize(b)+"Ids";this.attrMap(j,f||"*",!0).attrDecoder(j,function(a){a&&i(a,this[b])}).attrEncoder(j,function(){for(var a=[],c=this[b],d=0,e=c.length;e>d;d++)a.push(c[d].$pk);return a})}return this}};return f.mixin(function(){this.extend("attrAsCollection",j.attrAsCollection,["hasMany","path","source","inverseOf","params","hooks"]).extend("attrAsResource",j.attrAsResource,["hasOne","path","source","inverseOf","hooks"]).extend("attrAsReference",j.attrAsReference,["belongsTo","key","prefetch"]).extend("attrAsReferenceToMany",j.attrAsReferenceToMany,["belongsToMany","keys"])})}]),c.factory("RMModelFactory",["$injector","inflector","RMUtils","RMScopeApi","RMCommonApi","RMRecordApi","RMListApi","RMCollectionApi","RMExtendedApi","RMSerializer","RMBuilder",function(c,d,e,f,g,h,i,j,k,l,m){var n=/(.*?)([^\/]+)\/?$/,o=e.extendOverriden;return function(c,p){function q(a,b){this.$scope=a||q,this.$pk=b,this.$initialize()}function r(a,b){var c=new A;return c.$scope=b||q,c.$params=a,c.$initialize(),c}function s(a,b,c){var d=D[a];e.assert(!!d,"Invalid api name $1",a),b?d[b]=e.override(d[b],c):e.extendOverriden(d,c)}c=e.cleanUrl(c);var t,u={primaryKey:"id",urlPrefix:null},v=new l(q),w=[],x=[],y={},z={};!u.name&&c&&(u.name=d.singularize(c.replace(n,"$2"))),!u.plural&&u.name&&(u.plural=d.pluralize(u.name));var A=e.buildArrayType(),B=e.buildArrayType(),C=function(a){this.$isCollection=a,this.$initialize()};o(q,{$$getDescription:function(a){return y[a]},$$chain:[],$type:q,$new:function(a,b){return new q(b||q,a)},$collection:r,$url:function(){return u.urlPrefix?e.joinUrl(u.urlPrefix,c):c},$dispatch:function(a,b,c){var d,e,f=z[a];if(f)for(d=0;e=f[d];d++)e.apply(c||this,b||[]);return this},inferKey:function(a){return a&&"undefined"!=typeof a[u.primaryKey]?a[u.primaryKey]:null},getProperty:function(a,c){var d=u[a];return d!==b?d:c},isNested:function(){return!c},single:function(a){return new q({$urlFor:function(){return u.urlPrefix?e.joinUrl(u.urlPrefix,a):a}},"")},dummy:function(a){return new C(a)},list:function(a){var b=new B;return a&&b.push.apply(b,a),b},identity:function(a){return a?u.plural:u.name},mix:function(){return t.chain(arguments),this.$$chain.push.apply(this.$$chain,arguments),this},unpack:function(a,b){return b},pack:function(a,b){return b},decode:v.decode,encode:v.encode,decodeName:null,encodeName:null},f),o(q.prototype,{$type:q,$initialize:function(){var a,b,c=this;for(b=0;a=w[b];b++)this[a[0]]="function"==typeof a[1]?a[1].apply(this):a[1];for(b=0;a=x[b];b++)Object.defineProperty(c,a[0],{enumerable:!0,get:a[1]})}},g,h,k),o(A.prototype,{$type:q,$new:function(a,b){return q.$new(a,b||this)},$collection:function(b,c){return b=this.$params?a.extend({},this.$params,b):b,r(b,c||this.$scope)}},i,f,g,j,k),o(B.prototype,{$type:q},i,g),o(C.prototype,{$type:q,$initialize:function(){}},g);var D={Model:q,Record:q.prototype,Collection:A.prototype,List:B.prototype,Dummy:C.prototype};return t=new m(a.extend(v.dsl(),{setProperty:function(a,b){return u[a]=b,this},attrDefault:function(a,b){return w.push([a,b]),this},attrComputed:function(a,b){return x.push([a,b]),this.attrMask(a,!0),this},attrMeta:function(a,b){return y[a]=o(y[a]||{},b),this},define:function(a,b){var c=!1,d="Record";switch("object"==typeof b&&b?d=a:(c=a.split("."),1===c.length?c=c[0]:(d=c[0],c=c[1])),d){case"List":s("Collection",c,b),s("List",c,b);break;case"Scope":s("Model",c,b),s("Collection",c,b);break;case"Resource":s("Record",c,b),s("Collection",c,b),s("List",c,b),s("Dummy",c,b);break;default:s(d,c,b)}return this},on:function(a,b){return(z[a]||(z[a]=[])).push(b),this}})),t.chain(p),q}}]),c.factory("RMFastQ",[function(){function b(a,e){return a&&d(a.then)?c(a):{simple:!0,then:function(c,d){return b(e?d(a):c(a))},"finally":function(f){var g=f();return g&&d(a.then)?c(a.then(function(){return e?b(a,!0):a},function(){return e?b(a,!0):a})):this}}}function c(a){if(a.simple)return a;var d;return a.then(function(a){d=b(a)},function(a){d=b(a,!0)}),{then:function(b,e){return d?d.then(b,e):c(a.then(b,e))},"finally":function(b){return d?d["finally"](b):c(a["finally"](b))}}}var d=a.isFunction;return{reject:function(a){return b(a,!0)},when:function(a){return b(a,!1)},wrap:c}}]),c.factory("RMPackerCache",[function(){var a;return{feed:function(b,c){a[b]=c},resolve:function(b){if(a){var c=b.$type,d=a[c.identity(!0)];if(d&&b.$pk)for(var e=0,f=d.length;f>e;e++)if(b.$pk===c.inferKey(d[e])){b.$decode(d[e]);break}}return b},prepare:function(){a={}},clear:function(){a=null}}}]),c.factory("RMSerializer",["$injector","inflector","$filter","RMUtils",function(c,d,e,f){function g(a,b){for(var c,d=0;a&&(c=b[d]);d++)a=a[c];return a}function h(a,b,c){for(var d=0,e=b.length-1;e>d;d++){var f=b[d];a=a[f]||(a[f]={})}a[b[b.length-1]]=c}return function(c){function d(a,b){if("function"==typeof b)return b(a);var c=n[a];return c&&(c===!0||-1!==c.indexOf(b))}function i(a,e,f,h,i){var k,l,m,n,o,p,s,t,u=f?f+".":"";if(o=r[f])for(s=0,t=o.length;t>s;s++)m=u+o[s].path,d(m,h)||(n=o[s].map?g(a,o[s].map):a[c.encodeName?c.encodeName(o[s].path):o[s].path],(o[s].forced||n!==b)&&(n=j(n,m,h,i),n!==b&&(e[o[s].path]=n)));for(k in a)if(a.hasOwnProperty(k)){if(l=c.decodeName?c.decodeName(k):k,"$"===l[0])continue;if(o){for(p=!1,s=0,t=o.length;t>s&&!(p=o[s].mapPath===k);s++);if(p)continue}if(m=u+l,q[m]||d(m,h))continue;n=j(a[k],m,h,i),n!==b&&(e[l]=n)}}function j(a,b,c,d){var e=o[b],f=a;if(e)f=e.call(d,a);else if("object"==typeof a)if(m(a)){f=[];for(var g=0,h=a.length;h>g;g++)f.push(j(a[g],b+"[]",c,d))}else a&&(f={},i(a,f,b,c,d));return f}function k(a,e,f,g,i){var j,k,m,n,o,p=f?f+".":"";for(j in a)if(a.hasOwnProperty(j)&&"$"!==j[0]){if(k=p+j,q[k]||d(k,g))continue;n=l(a[j],k,g,i),n!==b&&(m=c.encodeName?c.encodeName(j):j,e[m]=n),s[k]&&delete a[j]}if(o=r[f])for(var t=0,u=o.length;u>t;t++)k=p+o[t].path,d(k,g)||(n=a[o[t].path],(o[t].forced||n!==b)&&(n=l(n,k,g,i),n!==b&&(o[t].map?h(e,o[t].map,n):e[c.encodeName?c.encodeName(o[t].path):o[t].path]=n)))}function l(a,b,c,d){var e=p[b],f=a;if(e)f=e.call(d,a);else if(null!==a&&"object"==typeof a&&"function"!=typeof a.toJSON)if(m(a)){f=[];for(var g=0,h=a.length;h>g;g++)f.push(l(a[g],b+"[]",c,d))}else a&&(f={},k(a,f,b,c,d));return f}var m=a.isArray,n={},o={},p={},q={},r={},s={};return{decode:function(a,b,c){i(b,a,"",c,a)},encode:function(a,b){var c={};return k(a,c,"",b,a),c},dsl:function(){return{attrMap:function(a,b,c){var d=a.lastIndexOf("."),e=-1!==d?a.substr(0,d):"",f=-1!==d?a.substr(d+1):a;q[a]=!0;var g=r[e]||(r[e]=[]);return g.push({path:f,map:"*"===b?null:b.split("."),mapPath:b,forced:c}),this},attrMask:function(a,b){return b?n[a]=b:delete n[a],this},attrDecoder:function(a,b,c,d){if("string"==typeof b){var g=e(b);b=function(a){return g(a,c)}}return o[a]=d?f.chain(o[a],b):b,this},attrEncoder:function(a,b,c,d){if("string"==typeof b){var g=e(b);b=function(a){return g(a,c)}}return p[a]=d?f.chain(p[a],b):b,this},attrVolatile:function(a,c){return s[a]=c===b?!0:c,this}}}}}}]),c.factory("DefaultPacker",["restmod","inflector","RMPackerCache",function(b,c,d){function e(a,b,c){for(var d=0,e=b.length;e>d;d++)c(b[d],a[b[d]])}function f(a,b,c){for(var d in a)a.hasOwnProperty(d)&&-1===b.indexOf(d)&&c(d,a[d])}function g(b,c,d,g,h){if("."===d||d===!0){var i=[c];g&&i.push.apply(i,a.isArray(g)?g:[g]),f(b,i,h)}else"string"==typeof d?f(b[d],[],h):e(b,d,h)}return b.mixin(function(){this.define("Model.unpack",function(a,b){var c=null,e=this.getProperty("jsonLinks","linked"),f=this.getProperty("jsonMeta","meta");return c=a.$isCollection?this.getProperty("jsonRootMany")||this.getProperty("jsonRoot")||this.getProperty("plural"):this.getProperty("jsonRootSingle")||this.getProperty("jsonRoot")||this.getProperty("name"),f&&(a.$metadata={},g(b,c,f,e,function(b,c){a.$metadata[b]=c})),e&&g(b,c,e,f,function(a,b){d.feed(a,b)}),b[c]})})}]),c.factory("RMUtils",["$log",function(a){var b=[],c=function(){var a=function(){};return Object.setPrototypeOf?function(a,b){Object.setPrototypeOf(a,b)}:(new a).__proto__===a.prototype?function(a,b){a.__proto__=b}:void 0}(),d={CREATE_MASK:"C",UPDATE_MASK:"U",READ_MASK:"R",WRITE_MASK:"CU",FULL_MASK:"CRU",format:function(a,b){for(var c=0;b&&cparent.RestmodArray = Array;"),d=window.RestmodArray,delete window.RestmodArray;for(var g in Array.prototype)"function"!=typeof Array.prototype[g]||d.prototype[g]||(d.prototype[g]=Array.prototype[g]);document.body.removeChild(f),b.push(f)}return d}};return d}])}(angular);
\ No newline at end of file
+!function(a,b){"use strict";!function(a){a.module("platanus.inflector",[]).provider("inflector",[function(){function a(a,b,c){if(-1===c.indexOf(a.toLowerCase()))for(var d,e=0;d=b[e++];)if(a.match(d[0]))return a.replace(d[0],d[1]);return a}var b="en",c={en:{uncountable:["music","art","love","happiness","advice","furniture","luggage","sugar","butter","water","electricity","gas","power","currency","equipment","information","rice","money","species","series","fish","sheep","moose","deer","news"],plural:[[new RegExp("(m)an$","gi"),"$1en"],[new RegExp("(pe)rson$","gi"),"$1ople"],[new RegExp("(child)$","gi"),"$1ren"],[new RegExp("^(ox)$","gi"),"$1en"],[new RegExp("(ax|test)is$","gi"),"$1es"],[new RegExp("(octop|vir)us$","gi"),"$1i"],[new RegExp("(alias|status)$","gi"),"$1es"],[new RegExp("(bu)s$","gi"),"$1ses"],[new RegExp("(buffal|tomat|potat)o$","gi"),"$1oes"],[new RegExp("([ti])um$","gi"),"$1a"],[new RegExp("sis$","gi"),"ses"],[new RegExp("(?:([^f])fe|([lr])f)$","gi"),"$1$2ves"],[new RegExp("(hive)$","gi"),"$1s"],[new RegExp("([^aeiouy]|qu)y$","gi"),"$1ies"],[new RegExp("(x|ch|ss|sh)$","gi"),"$1es"],[new RegExp("(matr|vert|ind)ix|ex$","gi"),"$1ices"],[new RegExp("([m|l])ouse$","gi"),"$1ice"],[new RegExp("(quiz)$","gi"),"$1zes"],[new RegExp("s$","gi"),"s"],[new RegExp("$","gi"),"s"]],singular:[[new RegExp("(m)en$","gi"),"$1an"],[new RegExp("(pe)ople$","gi"),"$1rson"],[new RegExp("(child)ren$","gi"),"$1"],[new RegExp("([ti])a$","gi"),"$1um"],[new RegExp("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$","gi"),"$1$2sis"],[new RegExp("(hive)s$","gi"),"$1"],[new RegExp("(tive)s$","gi"),"$1"],[new RegExp("(curve)s$","gi"),"$1"],[new RegExp("([lr])ves$","gi"),"$1f"],[new RegExp("([^fo])ves$","gi"),"$1fe"],[new RegExp("([^aeiouy]|qu)ies$","gi"),"$1y"],[new RegExp("(s)eries$","gi"),"$1eries"],[new RegExp("(m)ovies$","gi"),"$1ovie"],[new RegExp("(x|ch|ss|sh)es$","gi"),"$1"],[new RegExp("([m|l])ice$","gi"),"$1ouse"],[new RegExp("(bus)es$","gi"),"$1"],[new RegExp("(o)es$","gi"),"$1"],[new RegExp("(shoe)s$","gi"),"$1"],[new RegExp("(cris|ax|test)es$","gi"),"$1is"],[new RegExp("(octop|vir)i$","gi"),"$1us"],[new RegExp("(alias|status)es$","gi"),"$1"],[new RegExp("^(ox)en","gi"),"$1"],[new RegExp("(vert|ind)ices$","gi"),"$1ex"],[new RegExp("(matr)ices$","gi"),"$1ix"],[new RegExp("(quiz)zes$","gi"),"$1"],[new RegExp("s$","gi"),""]]}};return{registerLocale:function(a,b){c[a]=b},setLocale:function(a){b=a},$get:["$log",function(d){function e(a){a=a||b;var e=c[a];return e||d.warn("Invalid inflector locale "+a),e}return{camelize:function(a,b){return"string"!=typeof a?a:a.replace(/(?:^[-_\s]*|[-_\s]+)([A-Z\d])/gi,function(a,c,d){return b||0!==d?c.toUpperCase():c})},parameterize:function(a,b){return"string"!=typeof a?a:a.replace(/(?:[A-Z]+|[0-9]+)/g,function(a,c){return 0===c?a:(b||"-")+a}).toLowerCase()},dasherize:function(a,b){return a.replace(/[-_\s]+/g,b||"-")},singularize:function(b,c){var d=e(c);return d?a(b,d.singular,d.uncountable):b},pluralize:function(b,c){var d=e(c);return d?a(b,d.plural,d.uncountable):b}}}]}}])}(a);var c=a.module("restmod",["ng","platanus.inflector"]);c.provider("restmod",[function(){function b(a){return function(b){b.invoke(a,this,{$builder:this})}}var c=["RMBuilderExt","RMBuilderRelations","RMBuilderComputed"];return{rebase:function(){var d,e,f=arguments.length;for(e=0;f>e;e++)d=arguments[e],(a.isArray(d)||a.isFunction(d))&&(d=b(d)),c.push(d);return this},$get:["RMModelFactory","$log",function(a,b){var d=Array.prototype.slice,e={model:function(e){var f=a(e,c);return arguments.length>1&&(f.mix(d.call(arguments,1)),b.warn("Passing mixins and difinitions in the model method will be deprecated in restmod 1.2, use restmod.model().mix() instead.")),f},mixin:function(){return{$isAbstract:!0,$$chain:d.call(arguments,0)}},singleton:function(a){return e.model.apply(this,arguments).single(a)}};return e}]}}]).factory("model",["restmod",function(a){return a.model}]).factory("mixin",["restmod",function(a){return a.mixin}]),c.factory("RMCollectionApi",["RMUtils",function(c){var d=a.extend;return{$isCollection:!0,$initialize:function(){this.$dispatch("after-collection-init")},$decode:function(b,d){c.assert(b&&a.isArray(b),"Collection $decode expected array");for(var e=0,f=b.length;f>e;e++)this.$buildRaw(b[e],d).$reveal();return this.$dispatch("after-feed-many",[b]),this},$encode:function(a){for(var b=[],c=0,d=this.length;d>c;c++)b.push(this[c].$encode(a));return this.$dispatch("before-render-many",[b]),b},$clear:function(){return this.$always(function(){this.length=0})},$fetch:function(a){return this.$action(function(){var b={method:"GET",url:this.$url("fetchMany"),params:this.$params};a&&(b.params=b.params?d(b.params,a):a),this.$dispatch("before-fetch-many",[b]).$send(b,function(a){this.$unwrap(a.data).$dispatch("after-fetch-many",[a])},function(a){this.$dispatch("after-fetch-many-error",[a])})})},$add:function(a,d){return c.assert(a.$type&&a.$type===this.$type,"Collection $add expects record of the same $type"),this.$action(function(){a.$position===b&&(d!==b?this.splice(d,0,a):this.push(a),a.$position=!0,this.$dispatch("after-add",[a]))})},$remove:function(a){return this.$action(function(){var c=this.$indexOf(a);-1!==c&&(this.splice(c,1),a.$position=b,this.$dispatch("after-remove",[a]))})},$indexOf:function(a){for(var b="function"==typeof a?a:!1,c=0,d=this.length;d>c;c++)if(b?b(this[c]):this[c]===a)return c;return-1}}}]),c.factory("RMCommonApi",["$http","RMFastQ","$log",function(c,d,e){function f(a,c){var d=a.$dispatcher();return function(e){var f=a.$promise;a.$promise=b;try{a.$last=e;var g=d?a.$decorate(d,c,[a]):c.call(a,a);return g===b?a.$promise:g}finally{a.$promise=f}}}var g=[],h={$url:function(a){if(a){if(a="$"+a+"UrlFor",this.$scope[a])return this.$scope[a](this)}else if(this.$scope.$canonicalUrlFor)return this.$scope.$canonicalUrlFor(this);return this.$scope.$urlFor(this)},$dispatch:function(a,c,d){var e,f,h,i=this.$$dsp;if(d||(d=this),i&&(this.$$dsp=b,i(a,c,d)),this.$$cb&&(e=this.$$cb[a]))for(f=0;h=e[f];f++)h.apply(d,c||g);return this.$scope&&this.$scope.$dispatch?this.$scope.$dispatch(a,c,d):this.$type&&this.$type.$dispatch(a,c,d),this.$$dsp=i,this},$on:function(a,b){var c=(this.$$cb||(this.$$cb={}))[a]||(this.$$cb[a]=[]);return c.push(b),this},$decorate:function(a,b,c){var d=this.$$dsp;this.$$dsp="function"!=typeof a&&a?function(b,c,e){d&&d.apply(null,arguments);var f=a[b];f&&f.apply(e,c||g)}:a;try{return b.apply(this,c)}finally{this.$$dsp=d}},$dispatcher:function(){return this.$$dsp},$asPromise:function(){var a=this;return this.$promise?this.$promise.then(function(){return a},function(){return d.reject(a)}):d.when(this)},$then:function(a,b){return this.$promise=this.$promise?this.$promise.then(a?f(this,a):a,b?f(this,b):b):d.when(f(this,a)(this)),this},$always:function(a){return this.$then(a,a)},$finally:function(a){return this.$promise=this.$promise["finally"](f(this,a)),this},$send:function(a,b,g){this.$type.getProperty("style")||e.warn("No API style base was selected, see the Api Integration FAQ for more information on this warning");var h=this.$$action;return this.$always(function(){return this.$response=null,this.$status="pending",this.$dispatch("before-request",[a]),c(a).then(f(this,function(){h&&h.canceled?this.$status="canceled":(this.$status="ok",this.$response=this.$last,this.$dispatch("after-request",[this.$last]),b&&b.call(this,this.$last))}),f(this,function(){return h&&h.canceled?void(this.$status="canceled"):(this.$status="error",this.$response=this.$last,this.$dispatch("after-request-error",[this.$last]),g&&g.call(this,this.$last),d.reject(this))}))})},$action:function(a){var b={canceled:!1},c=this.$pending||(this.$pending=[]);return c.push(b),this.$always(function(){var c=this.$$action;try{return b.canceled?d.reject(this):(this.$$action=b,a.call(this))}finally{this.$$action=c}}).$finally(function(){c.splice(c.indexOf(b),1)})},$cancel:function(){return this.$pending&&a.forEach(this.$pending,function(a){a.canceled=!0}),this},$hasPendingActions:function(){var b=0;return this.$pending&&a.forEach(this.$pending,function(a){a.canceled||b++}),b>0}};return h}]),c.factory("RMExtendedApi",["$q","RMPackerCache",function(a,b){return{$decode:function(a,b){return this.$resolved===!1&&this.$clear&&this.$clear(),this.$super(a,b),this.$resolved=!0,this},$unwrap:function(a,c){try{return b.prepare(),a=this.$type.unpack(this,a),this.$decode(a,c)}finally{b.clear()}},$wrap:function(a){var b=this.$encode(a);return b=this.$type.pack(this,b)},$reset:function(){return this.$cancel().$action(function(){this.$resolved=!1})},$resolve:function(a){return this.$action(function(){this.$dispatch("before-resolve",[]),this.$resolved||this.$fetch(a)})},$refresh:function(a){return this.$reset().$fetch(a)}}}]),c.factory("RMListApi",[function(){return{$asList:function(a){var b=this.$type.list(),c=this.$asPromise();return b.$promise=c.then(function(c){b.push.apply(b,a?a(c):c)}),b}}}]),c.factory("RMRecordApi",["RMUtils",function(a){var c=function(b,c,d){this.$scope=b,this.$target=c,this.$partial=a.cleanUrl(d)};return c.prototype={$nestedUrl:function(){return a.joinUrl(this.$scope.$url(),this.$partial)},$urlFor:function(a){return a.$isCollection||this.$target.isNested()?this.$nestedUrl():this.$target.$urlFor(a)},$fetchUrlFor:function(){return this.$nestedUrl()},$createUrlFor:function(){return null}},{$initialize:function(){this.$super(),this.$dispatch("after-init")},$buildUrl:function(c){return this.$pk===b||null===this.$pk?null:a.joinUrl(c.$url(),this.$pk+"")},$buildScope:function(a,b){return a.$buildOwnScope?void 0:new c(this,a,b)},$each:function(a,b){for(var c in this)this.hasOwnProperty(c)&&"$"!==c[0]&&a.call(b||this[c],this[c],c);return this},$decode:function(c,d){return this.$type.decode(this,c,d||a.READ_MASK),(this.$pk===b||null===this.$pk)&&(this.$pk=this.$type.inferKey(c)),this.$dispatch("after-feed",[c]),this},$encode:function(b){var c=this.$type.encode(this,b||a.CREATE_MASK);return this.$dispatch("before-render",[c]),c},$fetch:function(b){return this.$action(function(){var c=this.$url("fetch");a.assert(!!c,"Cant $fetch if resource is not bound");var d={method:"GET",url:c,params:b};this.$dispatch("before-fetch",[d]),this.$send(d,function(a){this.$unwrap(a.data),this.$dispatch("after-fetch",[a])},function(a){this.$dispatch("after-fetch-error",[a])})})},$extend:function(a){return this.$action(function(){for(var b in a)a.hasOwnProperty(b)&&"$"!==b[0]&&(this[b]=a[b])})},$update:function(a){return this.$extend(a).$save()},$save:function(c){return this.$action(function(){var d,e=this.$url("update");e?(d=c?{method:this.$type.getProperty("patchMethod","PATCH"),url:e,data:this.$wrap(function(a){for(var b=0,d=c.length;d>b;b++)if(a===c[b]||0===a.indexOf(c[b]+".")||0===c[b].indexOf(a+"."))return!1;return!0})}:{method:"PUT",url:e,data:this.$wrap(a.UPDATE_MASK)},this.$dispatch("before-update",[d,!!c]).$dispatch("before-save",[d]).$send(d,function(a){this.$unwrap(a.data).$dispatch("after-update",[a,!!c]).$dispatch("after-save",[a])},function(a){this.$dispatch("after-update-error",[a,!!c]).$dispatch("after-save-error",[a])})):(e=this.$url("create")||this.$scope.$url(),a.assert(!!e,"Cant $create if parent scope is not bound"),d={method:"POST",url:e,data:this.$wrap(a.CREATE_MASK)},this.$dispatch("before-save",[d]).$dispatch("before-create",[d]).$send(d,function(a){this.$unwrap(a.data),this.$scope.$isCollection&&this.$position===b&&!this.$preventReveal&&this.$scope.$add(this,this.$revealAt),this.$dispatch("after-create",[a]).$dispatch("after-save",[a])},function(a){this.$dispatch("after-create-error",[a]).$dispatch("after-save-error",[a])}))})},$destroy:function(){return this.$action(function(){var a=this.$url("destroy");if(a){var b={method:"DELETE",url:a};this.$dispatch("before-destroy",[b]).$send(b,function(a){this.$scope.$remove&&this.$scope.$remove(this),this.$dispatch("after-destroy",[a])},function(a){this.$dispatch("after-destroy-error",[a])})}else this.$scope.$remove&&this.$scope.$remove(this)})},$moveTo:function(a){return this.$position!==b||(this.$revealAt=a),this},$reveal:function(a){return a===b||a?this.$scope.$add(this,this.$revealAt):this.$preventReveal=!0,this}}}]),c.factory("RMScopeApi",["RMUtils",function(){return{$urlFor:function(a){var b=this.$type.isNested()?this:this.$type;return"function"==typeof a.$buildUrl?a.$buildUrl(b):b.$url()},$new:function(a,b){return this.$super(a,b)},$build:function(a){return this.$new().$extend(a)},$buildRaw:function(a,b){var c=this.$new(this.$type.inferKey(a));return c.$decode(a,b),c},$find:function(a,b){return this.$new(a).$resolve(b)},$create:function(a){return this.$build(a).$save()},$collection:function(a,b){return this.$super(a,b)},$search:function(a){return this.$collection(a).$fetch()}}}]),c.factory("RMBuilder",["$injector","inflector","$log","RMUtils",function(b,c,d,e){function f(a){var b={init:["attrDefault"],mask:["attrMask"],ignore:["attrMask"],map:["attrMap","force"],decode:["attrDecoder","param","chain"],encode:["attrEncoder","param","chain"],"volatile":["attrVolatile"]};this.dsl=k(a,{describe:function(a){return g(a,function(a,b){switch(b.charAt(0)){case"@":d.warn("Usage of @ in description objects will be removed in 1.2, use a $extend block instead"),this.define("Scope."+b.substring(1),a);break;case"~":b=c.parameterize(b.substring(1)),d.warn("Usage of ~ in description objects will be removed in 1.2, use a $hooks block instead"),this.on(b,a);break;default:if("$config"===b)for(var e in a)a.hasOwnProperty(e)&&this.setProperty(e,a[e]);else if("$extend"===b)for(var e in a)a.hasOwnProperty(e)&&this.define(e,a[e]);else if("$hooks"===b)for(var e in a)a.hasOwnProperty(e)&&this.on(e,a[e]);else l.test(b)?(d.warn("Usage of ~ in description objects will be removed in 1.2, use a $config block instead"),b=c.camelize(b.toLowerCase()),this.setProperty(b,a)):h(a)?this.attribute(b,a):j(a)?this.define(b,a):this.attrDefault(b,a)}},this),this},extend:function(a,c,d){return"string"==typeof a?(this[a]=e.override(this[name],c),d&&(b[d[0]]=d,d[0]=a)):e.extendOverriden(this,a),this},attribute:function(a,c){var d,e,f,g;for(d in c)if(c.hasOwnProperty(d)&&(e=b[d])){for(f=[a,c[d]],g=1;gb;b++)this.mixin(a[b])},mixin:function(a){a.$$chain?this.chain(a.$$chain):"string"==typeof a?this.mixin(b.get(a)):i(a)?this.chain(a):j(a)?a.call(this.dsl,b):this.dsl.describe(a)}},f}]),c.factory("RMBuilderComputed",["restmod",function(a){var b={attrAsComputed:function(a,b){return this.attrComputed(a,b),this}};return a.mixin(function(){this.extend("attrAsComputed",b.attrAsComputed,["computed"])})}]),c.factory("RMBuilderExt",["$injector","$parse","inflector","$log","restmod",function(b,c,d,e,f){var g=a.bind,h=a.isFunction,i={setUrlPrefix:function(a){return this.setProperty("urlPrefix",a)},setPrimaryKey:function(a){return this.setProperty("primaryKey",a)},attrSerializer:function(a,c,e){return"string"==typeof c&&(c=b.get(d.camelize(c,!0)+"Serializer")),h(c)&&(c=c(e)),c.decode&&this.attrDecoder(a,g(c,c.decode)),c.encode&&this.attrEncoder(a,g(c,c.encode)),this},attrExpression:function(a,b){var d=c(b);return this.on("after-feed",function(){this[a]=d(this)})}};return f.mixin(function(){this.extend("setUrlPrefix",i.setUrlPrefix).extend("setPrimaryKey",i.setPrimaryKey).extend("attrSerializer",i.attrSerializer,["serialize"])})}]),c.factory("RMBuilderRelations",["$injector","inflector","$log","RMUtils","restmod","RMPackerCache",function(a,c,d,e,f,g){function h(a,b){return function(){var c=this.$owner;this.$owner=b;try{return a.apply(this,arguments)}finally{this.$owner=c}}}function i(a,b,c){for(var d in b)b.hasOwnProperty(d)&&a.$on(d,h(b[d],c))}var j={attrAsCollection:function(b,c,f,g,h,j,k){var l,m;return this.attrDefault(b,function(){if("string"==typeof c&&(c=a.get(c),l=c.getProperty("hasMany",{}),m=l.hooks,h)){var e=c.$$getDescription(h);e&&"belongs_to"===e.relation||(d.warn("Must define an inverse belongsTo relation for inverseOf to work"),h=!1)}var g,n=this.$buildScope(c,f||c.encodeUrlName(b));if(g=c.$collection(j||null,n),m&&i(g,m,this),k&&i(g,k,this),g.$dispatch("after-has-many-init"),h){var o=this;g.$on("after-add",function(a){a[h]=o})}return g}),(g||f)&&this.attrMap(b,g||f),this.attrDecoder(b,function(a){this[b].$reset().$decode(a)}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"has_many"}),this},attrAsResource:function(b,c,f,g,h,j){var k,l;return this.attrDefault(b,function(){if("string"==typeof c&&(c=a.get(c),k=c.getProperty("hasOne",{}),l=k.hooks,h)){var e=c.$$getDescription(h);e&&"belongs_to"===e.relation||(d.warn("Must define an inverse belongsTo relation for inverseOf to work"),h=!1)}var g,m=this.$buildScope(c,f||c.encodeUrlName(b));return g=c.$new(null,m),l&&i(g,l,this),j&&i(g,j,this),g.$dispatch("after-has-one-init"),h&&(g[h]=this),g}),(g||f)&&this.attrMap(b,g||f),this.attrDecoder(b,function(a){this[b].$decode(a)}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"has_one"}),this},attrAsReference:function(c,d,f,h){function i(){"string"==typeof d&&(d=a.get(d))}return this.attrDefault(c,null).attrMask(c,e.WRITE_MASK).attrMeta(c,{relation:"belongs_to"}),this.attrDecoder(c,function(a){return null===a?null:(i(),void(this[c]&&this[c].$pk===d.inferKey(a)?this[c].$decode(a):this[c]=d.$buildRaw(a)))}),f!==!1&&this.attrMap(c+"Id",f||"*",!0).attrDecoder(c+"Id",function(a){a!==b&&(this[c]&&this[c].$pk===a||(null!==a&&a!==!1?(i(),this[c]=g.resolve(d.$new(a)),h&&this[c].$fetch()):this[c]=null))}).attrEncoder(c+"Id",function(){return this[c]?this[c].$pk:null}),this},attrAsReferenceToMany:function(b,d,f){function h(){"string"==typeof d&&(d=a.get(d))}function i(a,b){h(),b.length=0;for(var c=0,e=a.length;e>c;c++)b.push("object"==typeof a[c]?d.$buildRaw(a[c]):g.resolve(d.$new(a[c])))}if(this.attrDefault(b,function(){return[]}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"belongs_to_many"}),this.attrDecoder(b,function(a){a&&i(a,this[b])}),f!==!1){var j=c.singularize(b)+"Ids";this.attrMap(j,f||"*",!0).attrDecoder(j,function(a){a&&i(a,this[b])}).attrEncoder(j,function(){for(var a=[],c=this[b],d=0,e=c.length;e>d;d++)a.push(c[d].$pk);return a})}return this}};return f.mixin(function(){this.extend("attrAsCollection",j.attrAsCollection,["hasMany","path","source","inverseOf","params","hooks"]).extend("attrAsResource",j.attrAsResource,["hasOne","path","source","inverseOf","hooks"]).extend("attrAsReference",j.attrAsReference,["belongsTo","key","prefetch"]).extend("attrAsReferenceToMany",j.attrAsReferenceToMany,["belongsToMany","keys"])})}]),c.factory("RMModelFactory",["$injector","$log","inflector","RMUtils","RMScopeApi","RMCommonApi","RMRecordApi","RMListApi","RMCollectionApi","RMExtendedApi","RMSerializer","RMBuilder",function(c,d,e,f,g,h,i,j,k,l,m,n){var o=/(.*?)([^\/]+)\/?$/,p=f.extendOverriden;return function(c,q){function r(a,b){this.$scope=a||r,this.$pk=b,this.$initialize()}function s(a,b){var c=new B;return c.$scope=b||r,c.$params=a,c.$initialize(),c}function t(a,b,c){var d=E[a];f.assert(!!d,"Invalid api name $1",a),b?d[b]=f.override(d[b],c):f.extendOverriden(d,c)}c=f.cleanUrl(c);var u,v={primaryKey:"id",urlPrefix:null},w=new m(r),x=[],y=[],z={},A={};!v.name&&c&&(v.name=e.singularize(c.replace(o,"$2"))),!v.plural&&v.name&&(v.plural=e.pluralize(v.name));var B=f.buildArrayType(),C=f.buildArrayType(),D=function(a){this.$isCollection=a,this.$initialize()};p(r,{$$getDescription:function(a){return z[a]},$$chain:[],$type:r,$new:function(a,b){return new r(b||r,a)},$collection:s,$url:function(){return v.urlPrefix?f.joinUrl(v.urlPrefix,c):c},$dispatch:function(a,b,c){var d,e,f=A[a];if(f)for(d=0;e=f[d];d++)e.apply(c||this,b||[]);return this},inferKey:function(a){return a&&"undefined"!=typeof a[v.primaryKey]?a[v.primaryKey]:null},getProperty:function(a,c){var d=v[a];return d!==b?d:c},isNested:function(){return!c},single:function(a){return new r({$urlFor:function(){return v.urlPrefix?f.joinUrl(v.urlPrefix,a):a}},"")},dummy:function(a){return new D(a)},list:function(a){var b=new C;return a&&b.push.apply(b,a),b},identity:function(a){return a?v.plural:v.name},mix:function(){return u.chain(arguments),this.$$chain.push.apply(this.$$chain,arguments),this},unpack:function(a,b){return b},pack:function(a,b){return b},decode:w.decode,encode:w.encode,decodeName:null,encodeName:null,encodeUrlName:function(a){return d.warn("Default paremeterization of urls will be disabled in 1.2, override Model.encodeUrlName with inflector.parameterize in your base model to keep the same behaviour."),e.parameterize(a)}},g),p(r.prototype,{$type:r,$initialize:function(){var a,b,c=this;for(b=0;a=x[b];b++)this[a[0]]="function"==typeof a[1]?a[1].apply(this):a[1];for(b=0;a=y[b];b++)Object.defineProperty(c,a[0],{enumerable:!0,get:a[1]})}},h,i,l),p(B.prototype,{$type:r,$new:function(a,b){return r.$new(a,b||this)},$collection:function(b,c){return b=this.$params?a.extend({},this.$params,b):b,s(b,c||this.$scope)}},j,g,h,k,l),p(C.prototype,{$type:r},j,h),p(D.prototype,{$type:r,$initialize:function(){}},h);var E={Model:r,Record:r.prototype,Collection:B.prototype,List:C.prototype,Dummy:D.prototype};return u=new n(a.extend(w.dsl(),{setProperty:function(a,b){return v[a]=b,this},attrDefault:function(a,b){return x.push([a,b]),this},attrComputed:function(a,b){return y.push([a,b]),this.attrMask(a,!0),this},attrMeta:function(a,b){return z[a]=p(z[a]||{},b),this},define:function(a,b){var c=!1,d="Record";switch("object"==typeof b&&b?d=a:(c=a.split("."),1===c.length?c=c[0]:(d=c[0],c=c[1])),d){case"List":t("Collection",c,b),t("List",c,b);break;case"Scope":t("Model",c,b),t("Collection",c,b);break;case"Resource":t("Record",c,b),t("Collection",c,b),t("List",c,b),t("Dummy",c,b);break;default:t(d,c,b)}return this},on:function(a,b){return(A[a]||(A[a]=[])).push(b),this}})),u.chain(q),r}}]),c.factory("RMFastQ",[function(){function b(a,f){return a&&d(a.then)?c(a):{simple:!0,then:function(c,d){return b(f?d(a):c(a))},"catch":e,"finally":function(e){var g=e();return g&&d(a.then)?c(a.then(function(){return f?b(a,!0):a},function(){return f?b(a,!0):a})):this}}}function c(a){if(a.simple)return a;var d;return a.then(function(a){d=b(a)},function(a){d=b(a,!0)}),{then:function(b,e){return d?d.then(b,e):c(a.then(b,e))},"catch":e,"finally":function(b){return d?d["finally"](b):c(a["finally"](b))}}}var d=a.isFunction,e=function(a){return this.then(null,a)};return{reject:function(a){return b(a,!0)},when:function(a){return b(a,!1)},wrap:c}}]),c.factory("RMPackerCache",[function(){var a;return{feed:function(b,c){a[b]=c},resolve:function(b){if(a){var c=b.$type,d=a[c.identity(!0)];if(d&&b.$pk)for(var e=0,f=d.length;f>e;e++)if(b.$pk===c.inferKey(d[e])){b.$decode(d[e]);break}}return b},prepare:function(){a={}},clear:function(){a=null}}}]),c.factory("RMSerializer",["$injector","inflector","$filter","RMUtils",function(c,d,e,f){function g(a,b){for(var c,d=0;a&&(c=b[d]);d++)a=a[c];return a}function h(a,b,c){for(var d=0,e=b.length-1;e>d;d++){var f=b[d];a=a[f]||(a[f]={})}a[b[b.length-1]]=c}return function(c){function d(a,b){if("function"==typeof b)return b(a);var c=n[a];return c&&(c===!0||-1!==c.indexOf(b))}function i(a,e,f,h,i){var k,l,m,n,o,p,s,t,u=f?f+".":"";if(o=r[f])for(s=0,t=o.length;t>s;s++)m=u+o[s].path,d(m,h)||(n=o[s].map?g(a,o[s].map):a[c.encodeName?c.encodeName(o[s].path):o[s].path],(o[s].forced||n!==b)&&(n=j(n,m,h,i),n!==b&&(e[o[s].path]=n)));for(k in a)if(a.hasOwnProperty(k)){if(l=c.decodeName?c.decodeName(k):k,"$"===l[0])continue;if(o){for(p=!1,s=0,t=o.length;t>s&&!(p=o[s].mapPath===k);s++);if(p)continue}if(m=u+l,q[m]||d(m,h))continue;n=j(a[k],m,h,i),n!==b&&(e[l]=n)}}function j(a,b,c,d){var e=o[b],f=a;if(e)f=e.call(d,a);else if("object"==typeof a)if(m(a)){f=[];for(var g=0,h=a.length;h>g;g++)f.push(j(a[g],b+"[]",c,d))}else a&&(f={},i(a,f,b,c,d));return f}function k(a,e,f,g,i){var j,k,m,n,o,p=f?f+".":"";for(j in a)if(a.hasOwnProperty(j)&&"$"!==j[0]){if(k=p+j,q[k]||d(k,g))continue;n=l(a[j],k,g,i),n!==b&&(m=c.encodeName?c.encodeName(j):j,e[m]=n),s[k]&&delete a[j]}if(o=r[f])for(var t=0,u=o.length;u>t;t++)k=p+o[t].path,d(k,g)||(n=a[o[t].path],(o[t].forced||n!==b)&&(n=l(n,k,g,i),n!==b&&(o[t].map?h(e,o[t].map,n):e[c.encodeName?c.encodeName(o[t].path):o[t].path]=n)))}function l(a,b,c,d){var e=p[b],f=a;if(e)f=e.call(d,a);else if(null!==a&&"object"==typeof a&&"function"!=typeof a.toJSON)if(m(a)){f=[];for(var g=0,h=a.length;h>g;g++)f.push(l(a[g],b+"[]",c,d))}else a&&(f={},k(a,f,b,c,d));return f}var m=a.isArray,n={},o={},p={},q={},r={},s={};return{decode:function(a,b,c){i(b,a,"",c,a)},encode:function(a,b){var c={};return k(a,c,"",b,a),c},dsl:function(){return{attrMap:function(a,b,c){var d=a.lastIndexOf("."),e=-1!==d?a.substr(0,d):"",f=-1!==d?a.substr(d+1):a;q[a]=!0;var g=r[e]||(r[e]=[]);return g.push({path:f,map:"*"===b?null:b.split("."),mapPath:b,forced:c}),this},attrMask:function(a,b){return b?n[a]=b:delete n[a],this},attrDecoder:function(a,b,c,d){if("string"==typeof b){var g=e(b);b=function(a){return g(a,c)}}return o[a]=d?f.chain(o[a],b):b,this},attrEncoder:function(a,b,c,d){if("string"==typeof b){var g=e(b);b=function(a){return g(a,c)}}return p[a]=d?f.chain(p[a],b):b,this},attrVolatile:function(a,c){return s[a]=c===b?!0:c,this}}}}}}]),c.factory("DefaultPacker",["restmod","inflector","RMPackerCache",function(b,c,d){function e(a,b,c){for(var d=0,e=b.length;e>d;d++)c(b[d],a[b[d]])}function f(a,b,c){for(var d in a)a.hasOwnProperty(d)&&-1===b.indexOf(d)&&c(d,a[d])}function g(b,c,d,g,h){if("."===d||d===!0){var i=[c];g&&i.push.apply(i,a.isArray(g)?g:[g]),f(b,i,h)}else"string"==typeof d?f(b[d],[],h):e(b,d,h)}return b.mixin(function(){this.define("Model.unpack",function(a,b){var c=null,e=this.getProperty("jsonLinks","linked"),f=this.getProperty("jsonMeta","meta");return c=a.$isCollection?this.getProperty("jsonRootMany")||this.getProperty("jsonRoot")||this.getProperty("plural"):this.getProperty("jsonRootSingle")||this.getProperty("jsonRoot")||this.getProperty("name"),f&&(a.$metadata={},g(b,c,f,e,function(b,c){a.$metadata[b]=c})),e&&g(b,c,e,f,function(a,b){d.feed(a,b)}),b[c]})})}]),c.factory("RMUtils",["$log",function(a){var b=[],c=function(){var a=function(){};return Object.setPrototypeOf?function(a,b){Object.setPrototypeOf(a,b)}:(new a).__proto__===a.prototype?function(a,b){a.__proto__=b}:void 0}(),d={CREATE_MASK:"C",UPDATE_MASK:"U",READ_MASK:"R",WRITE_MASK:"CU",FULL_MASK:"CRU",format:function(a,b){for(var c=0;b&&cparent.RestmodArray = Array;"),d=window.RestmodArray,delete window.RestmodArray;for(var g in Array.prototype)"function"!=typeof Array.prototype[g]||d.prototype[g]||(d.prototype[g]=Array.prototype[g]);document.body.removeChild(f),b.push(f)}return d}};return d}])}(angular);
\ No newline at end of file
diff --git a/dist/angular-restmod.js b/dist/angular-restmod.js
index 4ff85a4..9b50357 100644
--- a/dist/angular-restmod.js
+++ b/dist/angular-restmod.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -449,8 +449,8 @@ RMModule.factory('RMCommonApi', ['$http', 'RMFastQ', '$log', function($http, $q,
if(_for) {
_for = '$' + _for + 'UrlFor';
if(this.$scope[_for]) return this.$scope[_for](this);
- } else if(this.$scope.$cannonicalUrlFor) {
- return this.$scope.$cannonicalUrlFor(this);
+ } else if(this.$scope.$canonicalUrlFor) {
+ return this.$scope.$canonicalUrlFor(this);
}
return this.$scope.$urlFor(this);
@@ -2156,7 +2156,7 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
}
}
- var scope = this.$buildScope(_model, _url || inflector.parameterize(_attr)), col; // TODO: name to url transformation should be a Model strategy
+ var scope = this.$buildScope(_model, _url || _model.encodeUrlName(_attr)), col;
// setup collection
col = _model.$collection(_params || null, scope);
@@ -2221,7 +2221,7 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
}
}
- var scope = this.$buildScope(_model, _url || inflector.parameterize(_attr)), inst;
+ var scope = this.$buildScope(_model, _url || _model.encodeUrlName(_attr)), inst;
// setup record
inst = _model.$new(null, scope);
@@ -2451,8 +2451,8 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
});
}]);
-RMModule.factory('RMModelFactory', ['$injector', 'inflector', 'RMUtils', 'RMScopeApi', 'RMCommonApi', 'RMRecordApi', 'RMListApi', 'RMCollectionApi', 'RMExtendedApi', 'RMSerializer', 'RMBuilder',
- function($injector, inflector, Utils, ScopeApi, CommonApi, RecordApi, ListApi, CollectionApi, ExtendedApi, Serializer, Builder) {
+RMModule.factory('RMModelFactory', ['$injector', '$log', 'inflector', 'RMUtils', 'RMScopeApi', 'RMCommonApi', 'RMRecordApi', 'RMListApi', 'RMCollectionApi', 'RMExtendedApi', 'RMSerializer', 'RMBuilder',
+ function($injector, $log, inflector, Utils, ScopeApi, CommonApi, RecordApi, ListApi, CollectionApi, ExtendedApi, Serializer, Builder) {
var NAME_RGX = /(.*?)([^\/]+)\/?$/,
extend = Utils.extendOverriden;
@@ -2785,7 +2785,25 @@ RMModule.factory('RMModelFactory', ['$injector', 'inflector', 'RMUtils', 'RMScop
* @params {string} _name Record name
* @return {string} Response (raw) name
*/
- encodeName: null
+ encodeName: null,
+
+ /**
+ * @memberof StaticApi#
+ *
+ * @description The model name to url encoding strategy
+ *
+ * This method is called when translating a name into an url fragment (mainly by relations).
+ *
+ * By default it uses the `inflector.parameterize` method, in 1.2 this will change and the default
+ * behaviour will be to do nothing.
+ *
+ * @params {string} _name local name
+ * @return {string} url fragment
+ */
+ encodeUrlName: function(_name) {
+ $log.warn('Default paremeterization of urls will be disabled in 1.2, override Model.encodeUrlName with inflector.parameterize in your base model to keep the same behaviour.');
+ return inflector.parameterize(_name);
+ }
}, ScopeApi);
@@ -3064,7 +3082,10 @@ RMModule.factory('RMModelFactory', ['$injector', 'inflector', 'RMUtils', 'RMScop
*/
RMModule.factory('RMFastQ', [function() {
- var isFunction = angular.isFunction;
+ var isFunction = angular.isFunction,
+ catchError = function(_error) {
+ return this.then(null, _error);
+ };
function simpleQ(_val, _withError) {
@@ -3076,6 +3097,7 @@ RMModule.factory('RMFastQ', [function() {
then: function(_success, _error) {
return simpleQ(_withError ? _error(_val) : _success(_val));
},
+ 'catch': catchError,
'finally': function(_cb) {
var result = _cb();
if(result && isFunction(_val.then)) {
@@ -3109,6 +3131,7 @@ RMModule.factory('RMFastQ', [function() {
simple.then(_success, _error) :
wrappedQ(_promise.then(_success, _error));
},
+ 'catch': catchError,
'finally': function(_cb) {
return simple ?
simple['finally'](_cb) :
diff --git a/dist/angular-restmod.min.js b/dist/angular-restmod.min.js
index 8b19e27..28ad9f8 100644
--- a/dist/angular-restmod.min.js
+++ b/dist/angular-restmod.min.js
@@ -1,8 +1,8 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-!function(a,b){"use strict";var c=a.module("restmod",["ng","platanus.inflector"]);c.provider("restmod",[function(){function b(a){return function(b){b.invoke(a,this,{$builder:this})}}var c=["RMBuilderExt","RMBuilderRelations","RMBuilderComputed"];return{rebase:function(){var d,e,f=arguments.length;for(e=0;f>e;e++)d=arguments[e],(a.isArray(d)||a.isFunction(d))&&(d=b(d)),c.push(d);return this},$get:["RMModelFactory","$log",function(a,b){var d=Array.prototype.slice,e={model:function(e){var f=a(e,c);return arguments.length>1&&(f.mix(d.call(arguments,1)),b.warn("Passing mixins and difinitions in the model method will be deprecated in restmod 1.2, use restmod.model().mix() instead.")),f},mixin:function(){return{$isAbstract:!0,$$chain:d.call(arguments,0)}},singleton:function(a){return e.model.apply(this,arguments).single(a)}};return e}]}}]).factory("model",["restmod",function(a){return a.model}]).factory("mixin",["restmod",function(a){return a.mixin}]),c.factory("RMCollectionApi",["RMUtils",function(c){var d=a.extend;return{$isCollection:!0,$initialize:function(){this.$dispatch("after-collection-init")},$decode:function(b,d){c.assert(b&&a.isArray(b),"Collection $decode expected array");for(var e=0,f=b.length;f>e;e++)this.$buildRaw(b[e],d).$reveal();return this.$dispatch("after-feed-many",[b]),this},$encode:function(a){for(var b=[],c=0,d=this.length;d>c;c++)b.push(this[c].$encode(a));return this.$dispatch("before-render-many",[b]),b},$clear:function(){return this.$always(function(){this.length=0})},$fetch:function(a){return this.$action(function(){var b={method:"GET",url:this.$url("fetchMany"),params:this.$params};a&&(b.params=b.params?d(b.params,a):a),this.$dispatch("before-fetch-many",[b]).$send(b,function(a){this.$unwrap(a.data).$dispatch("after-fetch-many",[a])},function(a){this.$dispatch("after-fetch-many-error",[a])})})},$add:function(a,d){return c.assert(a.$type&&a.$type===this.$type,"Collection $add expects record of the same $type"),this.$action(function(){a.$position===b&&(d!==b?this.splice(d,0,a):this.push(a),a.$position=!0,this.$dispatch("after-add",[a]))})},$remove:function(a){return this.$action(function(){var c=this.$indexOf(a);-1!==c&&(this.splice(c,1),a.$position=b,this.$dispatch("after-remove",[a]))})},$indexOf:function(a){for(var b="function"==typeof a?a:!1,c=0,d=this.length;d>c;c++)if(b?b(this[c]):this[c]===a)return c;return-1}}}]),c.factory("RMCommonApi",["$http","RMFastQ","$log",function(c,d,e){function f(a,c){var d=a.$dispatcher();return function(e){var f=a.$promise;a.$promise=b;try{a.$last=e;var g=d?a.$decorate(d,c,[a]):c.call(a,a);return g===b?a.$promise:g}finally{a.$promise=f}}}var g=[],h={$url:function(a){if(a){if(a="$"+a+"UrlFor",this.$scope[a])return this.$scope[a](this)}else if(this.$scope.$cannonicalUrlFor)return this.$scope.$cannonicalUrlFor(this);return this.$scope.$urlFor(this)},$dispatch:function(a,c,d){var e,f,h,i=this.$$dsp;if(d||(d=this),i&&(this.$$dsp=b,i(a,c,d)),this.$$cb&&(e=this.$$cb[a]))for(f=0;h=e[f];f++)h.apply(d,c||g);return this.$scope&&this.$scope.$dispatch?this.$scope.$dispatch(a,c,d):this.$type&&this.$type.$dispatch(a,c,d),this.$$dsp=i,this},$on:function(a,b){var c=(this.$$cb||(this.$$cb={}))[a]||(this.$$cb[a]=[]);return c.push(b),this},$decorate:function(a,b,c){var d=this.$$dsp;this.$$dsp="function"!=typeof a&&a?function(b,c,e){d&&d.apply(null,arguments);var f=a[b];f&&f.apply(e,c||g)}:a;try{return b.apply(this,c)}finally{this.$$dsp=d}},$dispatcher:function(){return this.$$dsp},$asPromise:function(){var a=this;return this.$promise?this.$promise.then(function(){return a},function(){return d.reject(a)}):d.when(this)},$then:function(a,b){return this.$promise=this.$promise?this.$promise.then(a?f(this,a):a,b?f(this,b):b):d.when(f(this,a)(this)),this},$always:function(a){return this.$then(a,a)},$finally:function(a){return this.$promise=this.$promise["finally"](f(this,a)),this},$send:function(a,b,g){this.$type.getProperty("style")||e.warn("No API style base was selected, see the Api Integration FAQ for more information on this warning");var h=this.$$action;return this.$always(function(){return this.$response=null,this.$status="pending",this.$dispatch("before-request",[a]),c(a).then(f(this,function(){h&&h.canceled?this.$status="canceled":(this.$status="ok",this.$response=this.$last,this.$dispatch("after-request",[this.$last]),b&&b.call(this,this.$last))}),f(this,function(){return h&&h.canceled?void(this.$status="canceled"):(this.$status="error",this.$response=this.$last,this.$dispatch("after-request-error",[this.$last]),g&&g.call(this,this.$last),d.reject(this))}))})},$action:function(a){var b={canceled:!1},c=this.$pending||(this.$pending=[]);return c.push(b),this.$always(function(){var c=this.$$action;try{return b.canceled?d.reject(this):(this.$$action=b,a.call(this))}finally{this.$$action=c}}).$finally(function(){c.splice(c.indexOf(b),1)})},$cancel:function(){return this.$pending&&a.forEach(this.$pending,function(a){a.canceled=!0}),this},$hasPendingActions:function(){var b=0;return this.$pending&&a.forEach(this.$pending,function(a){a.canceled||b++}),b>0}};return h}]),c.factory("RMExtendedApi",["$q","RMPackerCache",function(a,b){return{$decode:function(a,b){return this.$resolved===!1&&this.$clear&&this.$clear(),this.$super(a,b),this.$resolved=!0,this},$unwrap:function(a,c){try{return b.prepare(),a=this.$type.unpack(this,a),this.$decode(a,c)}finally{b.clear()}},$wrap:function(a){var b=this.$encode(a);return b=this.$type.pack(this,b)},$reset:function(){return this.$cancel().$action(function(){this.$resolved=!1})},$resolve:function(a){return this.$action(function(){this.$dispatch("before-resolve",[]),this.$resolved||this.$fetch(a)})},$refresh:function(a){return this.$reset().$fetch(a)}}}]),c.factory("RMListApi",[function(){return{$asList:function(a){var b=this.$type.list(),c=this.$asPromise();return b.$promise=c.then(function(c){b.push.apply(b,a?a(c):c)}),b}}}]),c.factory("RMRecordApi",["RMUtils",function(a){var c=function(b,c,d){this.$scope=b,this.$target=c,this.$partial=a.cleanUrl(d)};return c.prototype={$nestedUrl:function(){return a.joinUrl(this.$scope.$url(),this.$partial)},$urlFor:function(a){return a.$isCollection||this.$target.isNested()?this.$nestedUrl():this.$target.$urlFor(a)},$fetchUrlFor:function(){return this.$nestedUrl()},$createUrlFor:function(){return null}},{$initialize:function(){this.$super(),this.$dispatch("after-init")},$buildUrl:function(c){return this.$pk===b||null===this.$pk?null:a.joinUrl(c.$url(),this.$pk+"")},$buildScope:function(a,b){return a.$buildOwnScope?void 0:new c(this,a,b)},$each:function(a,b){for(var c in this)this.hasOwnProperty(c)&&"$"!==c[0]&&a.call(b||this[c],this[c],c);return this},$decode:function(c,d){return this.$type.decode(this,c,d||a.READ_MASK),(this.$pk===b||null===this.$pk)&&(this.$pk=this.$type.inferKey(c)),this.$dispatch("after-feed",[c]),this},$encode:function(b){var c=this.$type.encode(this,b||a.CREATE_MASK);return this.$dispatch("before-render",[c]),c},$fetch:function(b){return this.$action(function(){var c=this.$url("fetch");a.assert(!!c,"Cant $fetch if resource is not bound");var d={method:"GET",url:c,params:b};this.$dispatch("before-fetch",[d]),this.$send(d,function(a){this.$unwrap(a.data),this.$dispatch("after-fetch",[a])},function(a){this.$dispatch("after-fetch-error",[a])})})},$extend:function(a){return this.$action(function(){for(var b in a)a.hasOwnProperty(b)&&"$"!==b[0]&&(this[b]=a[b])})},$update:function(a){return this.$extend(a).$save()},$save:function(c){return this.$action(function(){var d,e=this.$url("update");e?(d=c?{method:this.$type.getProperty("patchMethod","PATCH"),url:e,data:this.$wrap(function(a){for(var b=0,d=c.length;d>b;b++)if(a===c[b]||0===a.indexOf(c[b]+".")||0===c[b].indexOf(a+"."))return!1;return!0})}:{method:"PUT",url:e,data:this.$wrap(a.UPDATE_MASK)},this.$dispatch("before-update",[d,!!c]).$dispatch("before-save",[d]).$send(d,function(a){this.$unwrap(a.data).$dispatch("after-update",[a,!!c]).$dispatch("after-save",[a])},function(a){this.$dispatch("after-update-error",[a,!!c]).$dispatch("after-save-error",[a])})):(e=this.$url("create")||this.$scope.$url(),a.assert(!!e,"Cant $create if parent scope is not bound"),d={method:"POST",url:e,data:this.$wrap(a.CREATE_MASK)},this.$dispatch("before-save",[d]).$dispatch("before-create",[d]).$send(d,function(a){this.$unwrap(a.data),this.$scope.$isCollection&&this.$position===b&&!this.$preventReveal&&this.$scope.$add(this,this.$revealAt),this.$dispatch("after-create",[a]).$dispatch("after-save",[a])},function(a){this.$dispatch("after-create-error",[a]).$dispatch("after-save-error",[a])}))})},$destroy:function(){return this.$action(function(){var a=this.$url("destroy");if(a){var b={method:"DELETE",url:a};this.$dispatch("before-destroy",[b]).$send(b,function(a){this.$scope.$remove&&this.$scope.$remove(this),this.$dispatch("after-destroy",[a])},function(a){this.$dispatch("after-destroy-error",[a])})}else this.$scope.$remove&&this.$scope.$remove(this)})},$moveTo:function(a){return this.$position!==b||(this.$revealAt=a),this},$reveal:function(a){return a===b||a?this.$scope.$add(this,this.$revealAt):this.$preventReveal=!0,this}}}]),c.factory("RMScopeApi",["RMUtils",function(){return{$urlFor:function(a){var b=this.$type.isNested()?this:this.$type;return"function"==typeof a.$buildUrl?a.$buildUrl(b):b.$url()},$new:function(a,b){return this.$super(a,b)},$build:function(a){return this.$new().$extend(a)},$buildRaw:function(a,b){var c=this.$new(this.$type.inferKey(a));return c.$decode(a,b),c},$find:function(a,b){return this.$new(a).$resolve(b)},$create:function(a){return this.$build(a).$save()},$collection:function(a,b){return this.$super(a,b)},$search:function(a){return this.$collection(a).$fetch()}}}]),c.factory("RMBuilder",["$injector","inflector","$log","RMUtils",function(b,c,d,e){function f(a){var b={init:["attrDefault"],mask:["attrMask"],ignore:["attrMask"],map:["attrMap","force"],decode:["attrDecoder","param","chain"],encode:["attrEncoder","param","chain"],"volatile":["attrVolatile"]};this.dsl=k(a,{describe:function(a){return g(a,function(a,b){switch(b.charAt(0)){case"@":d.warn("Usage of @ in description objects will be removed in 1.2, use a $extend block instead"),this.define("Scope."+b.substring(1),a);break;case"~":b=c.parameterize(b.substring(1)),d.warn("Usage of ~ in description objects will be removed in 1.2, use a $hooks block instead"),this.on(b,a);break;default:if("$config"===b)for(var e in a)a.hasOwnProperty(e)&&this.setProperty(e,a[e]);else if("$extend"===b)for(var e in a)a.hasOwnProperty(e)&&this.define(e,a[e]);else if("$hooks"===b)for(var e in a)a.hasOwnProperty(e)&&this.on(e,a[e]);else l.test(b)?(d.warn("Usage of ~ in description objects will be removed in 1.2, use a $config block instead"),b=c.camelize(b.toLowerCase()),this.setProperty(b,a)):h(a)?this.attribute(b,a):j(a)?this.define(b,a):this.attrDefault(b,a)}},this),this},extend:function(a,c,d){return"string"==typeof a?(this[a]=e.override(this[name],c),d&&(b[d[0]]=d,d[0]=a)):e.extendOverriden(this,a),this},attribute:function(a,c){var d,e,f,g;for(d in c)if(c.hasOwnProperty(d)&&(e=b[d])){for(f=[a,c[d]],g=1;gb;b++)this.mixin(a[b])},mixin:function(a){a.$$chain?this.chain(a.$$chain):"string"==typeof a?this.mixin(b.get(a)):i(a)?this.chain(a):j(a)?a.call(this.dsl,b):this.dsl.describe(a)}},f}]),c.factory("RMBuilderComputed",["restmod",function(a){var b={attrAsComputed:function(a,b){return this.attrComputed(a,b),this}};return a.mixin(function(){this.extend("attrAsComputed",b.attrAsComputed,["computed"])})}]),c.factory("RMBuilderExt",["$injector","$parse","inflector","$log","restmod",function(b,c,d,e,f){var g=a.bind,h=a.isFunction,i={setUrlPrefix:function(a){return this.setProperty("urlPrefix",a)},setPrimaryKey:function(a){return this.setProperty("primaryKey",a)},attrSerializer:function(a,c,e){return"string"==typeof c&&(c=b.get(d.camelize(c,!0)+"Serializer")),h(c)&&(c=c(e)),c.decode&&this.attrDecoder(a,g(c,c.decode)),c.encode&&this.attrEncoder(a,g(c,c.encode)),this},attrExpression:function(a,b){var d=c(b);return this.on("after-feed",function(){this[a]=d(this)})}};return f.mixin(function(){this.extend("setUrlPrefix",i.setUrlPrefix).extend("setPrimaryKey",i.setPrimaryKey).extend("attrSerializer",i.attrSerializer,["serialize"])})}]),c.factory("RMBuilderRelations",["$injector","inflector","$log","RMUtils","restmod","RMPackerCache",function(a,c,d,e,f,g){function h(a,b){return function(){var c=this.$owner;this.$owner=b;try{return a.apply(this,arguments)}finally{this.$owner=c}}}function i(a,b,c){for(var d in b)b.hasOwnProperty(d)&&a.$on(d,h(b[d],c))}var j={attrAsCollection:function(b,f,g,h,j,k,l){var m,n;return this.attrDefault(b,function(){if("string"==typeof f&&(f=a.get(f),m=f.getProperty("hasMany",{}),n=m.hooks,j)){var e=f.$$getDescription(j);e&&"belongs_to"===e.relation||(d.warn("Must define an inverse belongsTo relation for inverseOf to work"),j=!1)}var h,o=this.$buildScope(f,g||c.parameterize(b));if(h=f.$collection(k||null,o),n&&i(h,n,this),l&&i(h,l,this),h.$dispatch("after-has-many-init"),j){var p=this;h.$on("after-add",function(a){a[j]=p})}return h}),(h||g)&&this.attrMap(b,h||g),this.attrDecoder(b,function(a){this[b].$reset().$decode(a)}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"has_many"}),this},attrAsResource:function(b,f,g,h,j,k){var l,m;return this.attrDefault(b,function(){if("string"==typeof f&&(f=a.get(f),l=f.getProperty("hasOne",{}),m=l.hooks,j)){var e=f.$$getDescription(j);e&&"belongs_to"===e.relation||(d.warn("Must define an inverse belongsTo relation for inverseOf to work"),j=!1)}var h,n=this.$buildScope(f,g||c.parameterize(b));return h=f.$new(null,n),m&&i(h,m,this),k&&i(h,k,this),h.$dispatch("after-has-one-init"),j&&(h[j]=this),h}),(h||g)&&this.attrMap(b,h||g),this.attrDecoder(b,function(a){this[b].$decode(a)}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"has_one"}),this},attrAsReference:function(c,d,f,h){function i(){"string"==typeof d&&(d=a.get(d))}return this.attrDefault(c,null).attrMask(c,e.WRITE_MASK).attrMeta(c,{relation:"belongs_to"}),this.attrDecoder(c,function(a){return null===a?null:(i(),void(this[c]&&this[c].$pk===d.inferKey(a)?this[c].$decode(a):this[c]=d.$buildRaw(a)))}),f!==!1&&this.attrMap(c+"Id",f||"*",!0).attrDecoder(c+"Id",function(a){a!==b&&(this[c]&&this[c].$pk===a||(null!==a&&a!==!1?(i(),this[c]=g.resolve(d.$new(a)),h&&this[c].$fetch()):this[c]=null))}).attrEncoder(c+"Id",function(){return this[c]?this[c].$pk:null}),this},attrAsReferenceToMany:function(b,d,f){function h(){"string"==typeof d&&(d=a.get(d))}function i(a,b){h(),b.length=0;for(var c=0,e=a.length;e>c;c++)b.push("object"==typeof a[c]?d.$buildRaw(a[c]):g.resolve(d.$new(a[c])))}if(this.attrDefault(b,function(){return[]}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"belongs_to_many"}),this.attrDecoder(b,function(a){a&&i(a,this[b])}),f!==!1){var j=c.singularize(b)+"Ids";this.attrMap(j,f||"*",!0).attrDecoder(j,function(a){a&&i(a,this[b])}).attrEncoder(j,function(){for(var a=[],c=this[b],d=0,e=c.length;e>d;d++)a.push(c[d].$pk);return a})}return this}};return f.mixin(function(){this.extend("attrAsCollection",j.attrAsCollection,["hasMany","path","source","inverseOf","params","hooks"]).extend("attrAsResource",j.attrAsResource,["hasOne","path","source","inverseOf","hooks"]).extend("attrAsReference",j.attrAsReference,["belongsTo","key","prefetch"]).extend("attrAsReferenceToMany",j.attrAsReferenceToMany,["belongsToMany","keys"])})}]),c.factory("RMModelFactory",["$injector","inflector","RMUtils","RMScopeApi","RMCommonApi","RMRecordApi","RMListApi","RMCollectionApi","RMExtendedApi","RMSerializer","RMBuilder",function(c,d,e,f,g,h,i,j,k,l,m){var n=/(.*?)([^\/]+)\/?$/,o=e.extendOverriden;return function(c,p){function q(a,b){this.$scope=a||q,this.$pk=b,this.$initialize()}function r(a,b){var c=new A;return c.$scope=b||q,c.$params=a,c.$initialize(),c}function s(a,b,c){var d=D[a];e.assert(!!d,"Invalid api name $1",a),b?d[b]=e.override(d[b],c):e.extendOverriden(d,c)}c=e.cleanUrl(c);var t,u={primaryKey:"id",urlPrefix:null},v=new l(q),w=[],x=[],y={},z={};!u.name&&c&&(u.name=d.singularize(c.replace(n,"$2"))),!u.plural&&u.name&&(u.plural=d.pluralize(u.name));var A=e.buildArrayType(),B=e.buildArrayType(),C=function(a){this.$isCollection=a,this.$initialize()};o(q,{$$getDescription:function(a){return y[a]},$$chain:[],$type:q,$new:function(a,b){return new q(b||q,a)},$collection:r,$url:function(){return u.urlPrefix?e.joinUrl(u.urlPrefix,c):c},$dispatch:function(a,b,c){var d,e,f=z[a];if(f)for(d=0;e=f[d];d++)e.apply(c||this,b||[]);return this},inferKey:function(a){return a&&"undefined"!=typeof a[u.primaryKey]?a[u.primaryKey]:null},getProperty:function(a,c){var d=u[a];return d!==b?d:c},isNested:function(){return!c},single:function(a){return new q({$urlFor:function(){return u.urlPrefix?e.joinUrl(u.urlPrefix,a):a}},"")},dummy:function(a){return new C(a)},list:function(a){var b=new B;return a&&b.push.apply(b,a),b},identity:function(a){return a?u.plural:u.name},mix:function(){return t.chain(arguments),this.$$chain.push.apply(this.$$chain,arguments),this},unpack:function(a,b){return b},pack:function(a,b){return b},decode:v.decode,encode:v.encode,decodeName:null,encodeName:null},f),o(q.prototype,{$type:q,$initialize:function(){var a,b,c=this;for(b=0;a=w[b];b++)this[a[0]]="function"==typeof a[1]?a[1].apply(this):a[1];for(b=0;a=x[b];b++)Object.defineProperty(c,a[0],{enumerable:!0,get:a[1]})}},g,h,k),o(A.prototype,{$type:q,$new:function(a,b){return q.$new(a,b||this)},$collection:function(b,c){return b=this.$params?a.extend({},this.$params,b):b,r(b,c||this.$scope)}},i,f,g,j,k),o(B.prototype,{$type:q},i,g),o(C.prototype,{$type:q,$initialize:function(){}},g);var D={Model:q,Record:q.prototype,Collection:A.prototype,List:B.prototype,Dummy:C.prototype};return t=new m(a.extend(v.dsl(),{setProperty:function(a,b){return u[a]=b,this},attrDefault:function(a,b){return w.push([a,b]),this},attrComputed:function(a,b){return x.push([a,b]),this.attrMask(a,!0),this},attrMeta:function(a,b){return y[a]=o(y[a]||{},b),this},define:function(a,b){var c=!1,d="Record";switch("object"==typeof b&&b?d=a:(c=a.split("."),1===c.length?c=c[0]:(d=c[0],c=c[1])),d){case"List":s("Collection",c,b),s("List",c,b);break;case"Scope":s("Model",c,b),s("Collection",c,b);break;case"Resource":s("Record",c,b),s("Collection",c,b),s("List",c,b),s("Dummy",c,b);break;default:s(d,c,b)}return this},on:function(a,b){return(z[a]||(z[a]=[])).push(b),this}})),t.chain(p),q}}]),c.factory("RMFastQ",[function(){function b(a,e){return a&&d(a.then)?c(a):{simple:!0,then:function(c,d){return b(e?d(a):c(a))},"finally":function(f){var g=f();return g&&d(a.then)?c(a.then(function(){return e?b(a,!0):a},function(){return e?b(a,!0):a})):this}}}function c(a){if(a.simple)return a;var d;return a.then(function(a){d=b(a)},function(a){d=b(a,!0)}),{then:function(b,e){return d?d.then(b,e):c(a.then(b,e))},"finally":function(b){return d?d["finally"](b):c(a["finally"](b))}}}var d=a.isFunction;return{reject:function(a){return b(a,!0)},when:function(a){return b(a,!1)},wrap:c}}]),c.factory("RMPackerCache",[function(){var a;return{feed:function(b,c){a[b]=c},resolve:function(b){if(a){var c=b.$type,d=a[c.identity(!0)];if(d&&b.$pk)for(var e=0,f=d.length;f>e;e++)if(b.$pk===c.inferKey(d[e])){b.$decode(d[e]);break}}return b},prepare:function(){a={}},clear:function(){a=null}}}]),c.factory("RMSerializer",["$injector","inflector","$filter","RMUtils",function(c,d,e,f){function g(a,b){for(var c,d=0;a&&(c=b[d]);d++)a=a[c];return a}function h(a,b,c){for(var d=0,e=b.length-1;e>d;d++){var f=b[d];a=a[f]||(a[f]={})}a[b[b.length-1]]=c}return function(c){function d(a,b){if("function"==typeof b)return b(a);var c=n[a];return c&&(c===!0||-1!==c.indexOf(b))}function i(a,e,f,h,i){var k,l,m,n,o,p,s,t,u=f?f+".":"";if(o=r[f])for(s=0,t=o.length;t>s;s++)m=u+o[s].path,d(m,h)||(n=o[s].map?g(a,o[s].map):a[c.encodeName?c.encodeName(o[s].path):o[s].path],(o[s].forced||n!==b)&&(n=j(n,m,h,i),n!==b&&(e[o[s].path]=n)));for(k in a)if(a.hasOwnProperty(k)){if(l=c.decodeName?c.decodeName(k):k,"$"===l[0])continue;if(o){for(p=!1,s=0,t=o.length;t>s&&!(p=o[s].mapPath===k);s++);if(p)continue}if(m=u+l,q[m]||d(m,h))continue;n=j(a[k],m,h,i),n!==b&&(e[l]=n)}}function j(a,b,c,d){var e=o[b],f=a;if(e)f=e.call(d,a);else if("object"==typeof a)if(m(a)){f=[];for(var g=0,h=a.length;h>g;g++)f.push(j(a[g],b+"[]",c,d))}else a&&(f={},i(a,f,b,c,d));return f}function k(a,e,f,g,i){var j,k,m,n,o,p=f?f+".":"";for(j in a)if(a.hasOwnProperty(j)&&"$"!==j[0]){if(k=p+j,q[k]||d(k,g))continue;n=l(a[j],k,g,i),n!==b&&(m=c.encodeName?c.encodeName(j):j,e[m]=n),s[k]&&delete a[j]}if(o=r[f])for(var t=0,u=o.length;u>t;t++)k=p+o[t].path,d(k,g)||(n=a[o[t].path],(o[t].forced||n!==b)&&(n=l(n,k,g,i),n!==b&&(o[t].map?h(e,o[t].map,n):e[c.encodeName?c.encodeName(o[t].path):o[t].path]=n)))}function l(a,b,c,d){var e=p[b],f=a;if(e)f=e.call(d,a);else if(null!==a&&"object"==typeof a&&"function"!=typeof a.toJSON)if(m(a)){f=[];for(var g=0,h=a.length;h>g;g++)f.push(l(a[g],b+"[]",c,d))}else a&&(f={},k(a,f,b,c,d));return f}var m=a.isArray,n={},o={},p={},q={},r={},s={};return{decode:function(a,b,c){i(b,a,"",c,a)},encode:function(a,b){var c={};return k(a,c,"",b,a),c},dsl:function(){return{attrMap:function(a,b,c){var d=a.lastIndexOf("."),e=-1!==d?a.substr(0,d):"",f=-1!==d?a.substr(d+1):a;q[a]=!0;var g=r[e]||(r[e]=[]);return g.push({path:f,map:"*"===b?null:b.split("."),mapPath:b,forced:c}),this},attrMask:function(a,b){return b?n[a]=b:delete n[a],this},attrDecoder:function(a,b,c,d){if("string"==typeof b){var g=e(b);b=function(a){return g(a,c)}}return o[a]=d?f.chain(o[a],b):b,this},attrEncoder:function(a,b,c,d){if("string"==typeof b){var g=e(b);b=function(a){return g(a,c)}}return p[a]=d?f.chain(p[a],b):b,this},attrVolatile:function(a,c){return s[a]=c===b?!0:c,this}}}}}}]),c.factory("DefaultPacker",["restmod","inflector","RMPackerCache",function(b,c,d){function e(a,b,c){for(var d=0,e=b.length;e>d;d++)c(b[d],a[b[d]])}function f(a,b,c){for(var d in a)a.hasOwnProperty(d)&&-1===b.indexOf(d)&&c(d,a[d])}function g(b,c,d,g,h){if("."===d||d===!0){var i=[c];g&&i.push.apply(i,a.isArray(g)?g:[g]),f(b,i,h)}else"string"==typeof d?f(b[d],[],h):e(b,d,h)}return b.mixin(function(){this.define("Model.unpack",function(a,b){var c=null,e=this.getProperty("jsonLinks","linked"),f=this.getProperty("jsonMeta","meta");return c=a.$isCollection?this.getProperty("jsonRootMany")||this.getProperty("jsonRoot")||this.getProperty("plural"):this.getProperty("jsonRootSingle")||this.getProperty("jsonRoot")||this.getProperty("name"),f&&(a.$metadata={},g(b,c,f,e,function(b,c){a.$metadata[b]=c})),e&&g(b,c,e,f,function(a,b){d.feed(a,b)}),b[c]})})}]),c.factory("RMUtils",["$log",function(a){var b=[],c=function(){var a=function(){};return Object.setPrototypeOf?function(a,b){Object.setPrototypeOf(a,b)}:(new a).__proto__===a.prototype?function(a,b){a.__proto__=b}:void 0}(),d={CREATE_MASK:"C",UPDATE_MASK:"U",READ_MASK:"R",WRITE_MASK:"CU",FULL_MASK:"CRU",format:function(a,b){for(var c=0;b&&cparent.RestmodArray = Array;"),d=window.RestmodArray,delete window.RestmodArray;for(var g in Array.prototype)"function"!=typeof Array.prototype[g]||d.prototype[g]||(d.prototype[g]=Array.prototype[g]);document.body.removeChild(f),b.push(f)}return d}};return d}])}(angular);
\ No newline at end of file
+!function(a,b){"use strict";var c=a.module("restmod",["ng","platanus.inflector"]);c.provider("restmod",[function(){function b(a){return function(b){b.invoke(a,this,{$builder:this})}}var c=["RMBuilderExt","RMBuilderRelations","RMBuilderComputed"];return{rebase:function(){var d,e,f=arguments.length;for(e=0;f>e;e++)d=arguments[e],(a.isArray(d)||a.isFunction(d))&&(d=b(d)),c.push(d);return this},$get:["RMModelFactory","$log",function(a,b){var d=Array.prototype.slice,e={model:function(e){var f=a(e,c);return arguments.length>1&&(f.mix(d.call(arguments,1)),b.warn("Passing mixins and difinitions in the model method will be deprecated in restmod 1.2, use restmod.model().mix() instead.")),f},mixin:function(){return{$isAbstract:!0,$$chain:d.call(arguments,0)}},singleton:function(a){return e.model.apply(this,arguments).single(a)}};return e}]}}]).factory("model",["restmod",function(a){return a.model}]).factory("mixin",["restmod",function(a){return a.mixin}]),c.factory("RMCollectionApi",["RMUtils",function(c){var d=a.extend;return{$isCollection:!0,$initialize:function(){this.$dispatch("after-collection-init")},$decode:function(b,d){c.assert(b&&a.isArray(b),"Collection $decode expected array");for(var e=0,f=b.length;f>e;e++)this.$buildRaw(b[e],d).$reveal();return this.$dispatch("after-feed-many",[b]),this},$encode:function(a){for(var b=[],c=0,d=this.length;d>c;c++)b.push(this[c].$encode(a));return this.$dispatch("before-render-many",[b]),b},$clear:function(){return this.$always(function(){this.length=0})},$fetch:function(a){return this.$action(function(){var b={method:"GET",url:this.$url("fetchMany"),params:this.$params};a&&(b.params=b.params?d(b.params,a):a),this.$dispatch("before-fetch-many",[b]).$send(b,function(a){this.$unwrap(a.data).$dispatch("after-fetch-many",[a])},function(a){this.$dispatch("after-fetch-many-error",[a])})})},$add:function(a,d){return c.assert(a.$type&&a.$type===this.$type,"Collection $add expects record of the same $type"),this.$action(function(){a.$position===b&&(d!==b?this.splice(d,0,a):this.push(a),a.$position=!0,this.$dispatch("after-add",[a]))})},$remove:function(a){return this.$action(function(){var c=this.$indexOf(a);-1!==c&&(this.splice(c,1),a.$position=b,this.$dispatch("after-remove",[a]))})},$indexOf:function(a){for(var b="function"==typeof a?a:!1,c=0,d=this.length;d>c;c++)if(b?b(this[c]):this[c]===a)return c;return-1}}}]),c.factory("RMCommonApi",["$http","RMFastQ","$log",function(c,d,e){function f(a,c){var d=a.$dispatcher();return function(e){var f=a.$promise;a.$promise=b;try{a.$last=e;var g=d?a.$decorate(d,c,[a]):c.call(a,a);return g===b?a.$promise:g}finally{a.$promise=f}}}var g=[],h={$url:function(a){if(a){if(a="$"+a+"UrlFor",this.$scope[a])return this.$scope[a](this)}else if(this.$scope.$canonicalUrlFor)return this.$scope.$canonicalUrlFor(this);return this.$scope.$urlFor(this)},$dispatch:function(a,c,d){var e,f,h,i=this.$$dsp;if(d||(d=this),i&&(this.$$dsp=b,i(a,c,d)),this.$$cb&&(e=this.$$cb[a]))for(f=0;h=e[f];f++)h.apply(d,c||g);return this.$scope&&this.$scope.$dispatch?this.$scope.$dispatch(a,c,d):this.$type&&this.$type.$dispatch(a,c,d),this.$$dsp=i,this},$on:function(a,b){var c=(this.$$cb||(this.$$cb={}))[a]||(this.$$cb[a]=[]);return c.push(b),this},$decorate:function(a,b,c){var d=this.$$dsp;this.$$dsp="function"!=typeof a&&a?function(b,c,e){d&&d.apply(null,arguments);var f=a[b];f&&f.apply(e,c||g)}:a;try{return b.apply(this,c)}finally{this.$$dsp=d}},$dispatcher:function(){return this.$$dsp},$asPromise:function(){var a=this;return this.$promise?this.$promise.then(function(){return a},function(){return d.reject(a)}):d.when(this)},$then:function(a,b){return this.$promise=this.$promise?this.$promise.then(a?f(this,a):a,b?f(this,b):b):d.when(f(this,a)(this)),this},$always:function(a){return this.$then(a,a)},$finally:function(a){return this.$promise=this.$promise["finally"](f(this,a)),this},$send:function(a,b,g){this.$type.getProperty("style")||e.warn("No API style base was selected, see the Api Integration FAQ for more information on this warning");var h=this.$$action;return this.$always(function(){return this.$response=null,this.$status="pending",this.$dispatch("before-request",[a]),c(a).then(f(this,function(){h&&h.canceled?this.$status="canceled":(this.$status="ok",this.$response=this.$last,this.$dispatch("after-request",[this.$last]),b&&b.call(this,this.$last))}),f(this,function(){return h&&h.canceled?void(this.$status="canceled"):(this.$status="error",this.$response=this.$last,this.$dispatch("after-request-error",[this.$last]),g&&g.call(this,this.$last),d.reject(this))}))})},$action:function(a){var b={canceled:!1},c=this.$pending||(this.$pending=[]);return c.push(b),this.$always(function(){var c=this.$$action;try{return b.canceled?d.reject(this):(this.$$action=b,a.call(this))}finally{this.$$action=c}}).$finally(function(){c.splice(c.indexOf(b),1)})},$cancel:function(){return this.$pending&&a.forEach(this.$pending,function(a){a.canceled=!0}),this},$hasPendingActions:function(){var b=0;return this.$pending&&a.forEach(this.$pending,function(a){a.canceled||b++}),b>0}};return h}]),c.factory("RMExtendedApi",["$q","RMPackerCache",function(a,b){return{$decode:function(a,b){return this.$resolved===!1&&this.$clear&&this.$clear(),this.$super(a,b),this.$resolved=!0,this},$unwrap:function(a,c){try{return b.prepare(),a=this.$type.unpack(this,a),this.$decode(a,c)}finally{b.clear()}},$wrap:function(a){var b=this.$encode(a);return b=this.$type.pack(this,b)},$reset:function(){return this.$cancel().$action(function(){this.$resolved=!1})},$resolve:function(a){return this.$action(function(){this.$dispatch("before-resolve",[]),this.$resolved||this.$fetch(a)})},$refresh:function(a){return this.$reset().$fetch(a)}}}]),c.factory("RMListApi",[function(){return{$asList:function(a){var b=this.$type.list(),c=this.$asPromise();return b.$promise=c.then(function(c){b.push.apply(b,a?a(c):c)}),b}}}]),c.factory("RMRecordApi",["RMUtils",function(a){var c=function(b,c,d){this.$scope=b,this.$target=c,this.$partial=a.cleanUrl(d)};return c.prototype={$nestedUrl:function(){return a.joinUrl(this.$scope.$url(),this.$partial)},$urlFor:function(a){return a.$isCollection||this.$target.isNested()?this.$nestedUrl():this.$target.$urlFor(a)},$fetchUrlFor:function(){return this.$nestedUrl()},$createUrlFor:function(){return null}},{$initialize:function(){this.$super(),this.$dispatch("after-init")},$buildUrl:function(c){return this.$pk===b||null===this.$pk?null:a.joinUrl(c.$url(),this.$pk+"")},$buildScope:function(a,b){return a.$buildOwnScope?void 0:new c(this,a,b)},$each:function(a,b){for(var c in this)this.hasOwnProperty(c)&&"$"!==c[0]&&a.call(b||this[c],this[c],c);return this},$decode:function(c,d){return this.$type.decode(this,c,d||a.READ_MASK),(this.$pk===b||null===this.$pk)&&(this.$pk=this.$type.inferKey(c)),this.$dispatch("after-feed",[c]),this},$encode:function(b){var c=this.$type.encode(this,b||a.CREATE_MASK);return this.$dispatch("before-render",[c]),c},$fetch:function(b){return this.$action(function(){var c=this.$url("fetch");a.assert(!!c,"Cant $fetch if resource is not bound");var d={method:"GET",url:c,params:b};this.$dispatch("before-fetch",[d]),this.$send(d,function(a){this.$unwrap(a.data),this.$dispatch("after-fetch",[a])},function(a){this.$dispatch("after-fetch-error",[a])})})},$extend:function(a){return this.$action(function(){for(var b in a)a.hasOwnProperty(b)&&"$"!==b[0]&&(this[b]=a[b])})},$update:function(a){return this.$extend(a).$save()},$save:function(c){return this.$action(function(){var d,e=this.$url("update");e?(d=c?{method:this.$type.getProperty("patchMethod","PATCH"),url:e,data:this.$wrap(function(a){for(var b=0,d=c.length;d>b;b++)if(a===c[b]||0===a.indexOf(c[b]+".")||0===c[b].indexOf(a+"."))return!1;return!0})}:{method:"PUT",url:e,data:this.$wrap(a.UPDATE_MASK)},this.$dispatch("before-update",[d,!!c]).$dispatch("before-save",[d]).$send(d,function(a){this.$unwrap(a.data).$dispatch("after-update",[a,!!c]).$dispatch("after-save",[a])},function(a){this.$dispatch("after-update-error",[a,!!c]).$dispatch("after-save-error",[a])})):(e=this.$url("create")||this.$scope.$url(),a.assert(!!e,"Cant $create if parent scope is not bound"),d={method:"POST",url:e,data:this.$wrap(a.CREATE_MASK)},this.$dispatch("before-save",[d]).$dispatch("before-create",[d]).$send(d,function(a){this.$unwrap(a.data),this.$scope.$isCollection&&this.$position===b&&!this.$preventReveal&&this.$scope.$add(this,this.$revealAt),this.$dispatch("after-create",[a]).$dispatch("after-save",[a])},function(a){this.$dispatch("after-create-error",[a]).$dispatch("after-save-error",[a])}))})},$destroy:function(){return this.$action(function(){var a=this.$url("destroy");if(a){var b={method:"DELETE",url:a};this.$dispatch("before-destroy",[b]).$send(b,function(a){this.$scope.$remove&&this.$scope.$remove(this),this.$dispatch("after-destroy",[a])},function(a){this.$dispatch("after-destroy-error",[a])})}else this.$scope.$remove&&this.$scope.$remove(this)})},$moveTo:function(a){return this.$position!==b||(this.$revealAt=a),this},$reveal:function(a){return a===b||a?this.$scope.$add(this,this.$revealAt):this.$preventReveal=!0,this}}}]),c.factory("RMScopeApi",["RMUtils",function(){return{$urlFor:function(a){var b=this.$type.isNested()?this:this.$type;return"function"==typeof a.$buildUrl?a.$buildUrl(b):b.$url()},$new:function(a,b){return this.$super(a,b)},$build:function(a){return this.$new().$extend(a)},$buildRaw:function(a,b){var c=this.$new(this.$type.inferKey(a));return c.$decode(a,b),c},$find:function(a,b){return this.$new(a).$resolve(b)},$create:function(a){return this.$build(a).$save()},$collection:function(a,b){return this.$super(a,b)},$search:function(a){return this.$collection(a).$fetch()}}}]),c.factory("RMBuilder",["$injector","inflector","$log","RMUtils",function(b,c,d,e){function f(a){var b={init:["attrDefault"],mask:["attrMask"],ignore:["attrMask"],map:["attrMap","force"],decode:["attrDecoder","param","chain"],encode:["attrEncoder","param","chain"],"volatile":["attrVolatile"]};this.dsl=k(a,{describe:function(a){return g(a,function(a,b){switch(b.charAt(0)){case"@":d.warn("Usage of @ in description objects will be removed in 1.2, use a $extend block instead"),this.define("Scope."+b.substring(1),a);break;case"~":b=c.parameterize(b.substring(1)),d.warn("Usage of ~ in description objects will be removed in 1.2, use a $hooks block instead"),this.on(b,a);break;default:if("$config"===b)for(var e in a)a.hasOwnProperty(e)&&this.setProperty(e,a[e]);else if("$extend"===b)for(var e in a)a.hasOwnProperty(e)&&this.define(e,a[e]);else if("$hooks"===b)for(var e in a)a.hasOwnProperty(e)&&this.on(e,a[e]);else l.test(b)?(d.warn("Usage of ~ in description objects will be removed in 1.2, use a $config block instead"),b=c.camelize(b.toLowerCase()),this.setProperty(b,a)):h(a)?this.attribute(b,a):j(a)?this.define(b,a):this.attrDefault(b,a)}},this),this},extend:function(a,c,d){return"string"==typeof a?(this[a]=e.override(this[name],c),d&&(b[d[0]]=d,d[0]=a)):e.extendOverriden(this,a),this},attribute:function(a,c){var d,e,f,g;for(d in c)if(c.hasOwnProperty(d)&&(e=b[d])){for(f=[a,c[d]],g=1;gb;b++)this.mixin(a[b])},mixin:function(a){a.$$chain?this.chain(a.$$chain):"string"==typeof a?this.mixin(b.get(a)):i(a)?this.chain(a):j(a)?a.call(this.dsl,b):this.dsl.describe(a)}},f}]),c.factory("RMBuilderComputed",["restmod",function(a){var b={attrAsComputed:function(a,b){return this.attrComputed(a,b),this}};return a.mixin(function(){this.extend("attrAsComputed",b.attrAsComputed,["computed"])})}]),c.factory("RMBuilderExt",["$injector","$parse","inflector","$log","restmod",function(b,c,d,e,f){var g=a.bind,h=a.isFunction,i={setUrlPrefix:function(a){return this.setProperty("urlPrefix",a)},setPrimaryKey:function(a){return this.setProperty("primaryKey",a)},attrSerializer:function(a,c,e){return"string"==typeof c&&(c=b.get(d.camelize(c,!0)+"Serializer")),h(c)&&(c=c(e)),c.decode&&this.attrDecoder(a,g(c,c.decode)),c.encode&&this.attrEncoder(a,g(c,c.encode)),this},attrExpression:function(a,b){var d=c(b);return this.on("after-feed",function(){this[a]=d(this)})}};return f.mixin(function(){this.extend("setUrlPrefix",i.setUrlPrefix).extend("setPrimaryKey",i.setPrimaryKey).extend("attrSerializer",i.attrSerializer,["serialize"])})}]),c.factory("RMBuilderRelations",["$injector","inflector","$log","RMUtils","restmod","RMPackerCache",function(a,c,d,e,f,g){function h(a,b){return function(){var c=this.$owner;this.$owner=b;try{return a.apply(this,arguments)}finally{this.$owner=c}}}function i(a,b,c){for(var d in b)b.hasOwnProperty(d)&&a.$on(d,h(b[d],c))}var j={attrAsCollection:function(b,c,f,g,h,j,k){var l,m;return this.attrDefault(b,function(){if("string"==typeof c&&(c=a.get(c),l=c.getProperty("hasMany",{}),m=l.hooks,h)){var e=c.$$getDescription(h);e&&"belongs_to"===e.relation||(d.warn("Must define an inverse belongsTo relation for inverseOf to work"),h=!1)}var g,n=this.$buildScope(c,f||c.encodeUrlName(b));if(g=c.$collection(j||null,n),m&&i(g,m,this),k&&i(g,k,this),g.$dispatch("after-has-many-init"),h){var o=this;g.$on("after-add",function(a){a[h]=o})}return g}),(g||f)&&this.attrMap(b,g||f),this.attrDecoder(b,function(a){this[b].$reset().$decode(a)}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"has_many"}),this},attrAsResource:function(b,c,f,g,h,j){var k,l;return this.attrDefault(b,function(){if("string"==typeof c&&(c=a.get(c),k=c.getProperty("hasOne",{}),l=k.hooks,h)){var e=c.$$getDescription(h);e&&"belongs_to"===e.relation||(d.warn("Must define an inverse belongsTo relation for inverseOf to work"),h=!1)}var g,m=this.$buildScope(c,f||c.encodeUrlName(b));return g=c.$new(null,m),l&&i(g,l,this),j&&i(g,j,this),g.$dispatch("after-has-one-init"),h&&(g[h]=this),g}),(g||f)&&this.attrMap(b,g||f),this.attrDecoder(b,function(a){this[b].$decode(a)}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"has_one"}),this},attrAsReference:function(c,d,f,h){function i(){"string"==typeof d&&(d=a.get(d))}return this.attrDefault(c,null).attrMask(c,e.WRITE_MASK).attrMeta(c,{relation:"belongs_to"}),this.attrDecoder(c,function(a){return null===a?null:(i(),void(this[c]&&this[c].$pk===d.inferKey(a)?this[c].$decode(a):this[c]=d.$buildRaw(a)))}),f!==!1&&this.attrMap(c+"Id",f||"*",!0).attrDecoder(c+"Id",function(a){a!==b&&(this[c]&&this[c].$pk===a||(null!==a&&a!==!1?(i(),this[c]=g.resolve(d.$new(a)),h&&this[c].$fetch()):this[c]=null))}).attrEncoder(c+"Id",function(){return this[c]?this[c].$pk:null}),this},attrAsReferenceToMany:function(b,d,f){function h(){"string"==typeof d&&(d=a.get(d))}function i(a,b){h(),b.length=0;for(var c=0,e=a.length;e>c;c++)b.push("object"==typeof a[c]?d.$buildRaw(a[c]):g.resolve(d.$new(a[c])))}if(this.attrDefault(b,function(){return[]}).attrMask(b,e.WRITE_MASK).attrMeta(b,{relation:"belongs_to_many"}),this.attrDecoder(b,function(a){a&&i(a,this[b])}),f!==!1){var j=c.singularize(b)+"Ids";this.attrMap(j,f||"*",!0).attrDecoder(j,function(a){a&&i(a,this[b])}).attrEncoder(j,function(){for(var a=[],c=this[b],d=0,e=c.length;e>d;d++)a.push(c[d].$pk);return a})}return this}};return f.mixin(function(){this.extend("attrAsCollection",j.attrAsCollection,["hasMany","path","source","inverseOf","params","hooks"]).extend("attrAsResource",j.attrAsResource,["hasOne","path","source","inverseOf","hooks"]).extend("attrAsReference",j.attrAsReference,["belongsTo","key","prefetch"]).extend("attrAsReferenceToMany",j.attrAsReferenceToMany,["belongsToMany","keys"])})}]),c.factory("RMModelFactory",["$injector","$log","inflector","RMUtils","RMScopeApi","RMCommonApi","RMRecordApi","RMListApi","RMCollectionApi","RMExtendedApi","RMSerializer","RMBuilder",function(c,d,e,f,g,h,i,j,k,l,m,n){var o=/(.*?)([^\/]+)\/?$/,p=f.extendOverriden;return function(c,q){function r(a,b){this.$scope=a||r,this.$pk=b,this.$initialize()}function s(a,b){var c=new B;return c.$scope=b||r,c.$params=a,c.$initialize(),c}function t(a,b,c){var d=E[a];f.assert(!!d,"Invalid api name $1",a),b?d[b]=f.override(d[b],c):f.extendOverriden(d,c)}c=f.cleanUrl(c);var u,v={primaryKey:"id",urlPrefix:null},w=new m(r),x=[],y=[],z={},A={};!v.name&&c&&(v.name=e.singularize(c.replace(o,"$2"))),!v.plural&&v.name&&(v.plural=e.pluralize(v.name));var B=f.buildArrayType(),C=f.buildArrayType(),D=function(a){this.$isCollection=a,this.$initialize()};p(r,{$$getDescription:function(a){return z[a]},$$chain:[],$type:r,$new:function(a,b){return new r(b||r,a)},$collection:s,$url:function(){return v.urlPrefix?f.joinUrl(v.urlPrefix,c):c},$dispatch:function(a,b,c){var d,e,f=A[a];if(f)for(d=0;e=f[d];d++)e.apply(c||this,b||[]);return this},inferKey:function(a){return a&&"undefined"!=typeof a[v.primaryKey]?a[v.primaryKey]:null},getProperty:function(a,c){var d=v[a];return d!==b?d:c},isNested:function(){return!c},single:function(a){return new r({$urlFor:function(){return v.urlPrefix?f.joinUrl(v.urlPrefix,a):a}},"")},dummy:function(a){return new D(a)},list:function(a){var b=new C;return a&&b.push.apply(b,a),b},identity:function(a){return a?v.plural:v.name},mix:function(){return u.chain(arguments),this.$$chain.push.apply(this.$$chain,arguments),this},unpack:function(a,b){return b},pack:function(a,b){return b},decode:w.decode,encode:w.encode,decodeName:null,encodeName:null,encodeUrlName:function(a){return d.warn("Default paremeterization of urls will be disabled in 1.2, override Model.encodeUrlName with inflector.parameterize in your base model to keep the same behaviour."),e.parameterize(a)}},g),p(r.prototype,{$type:r,$initialize:function(){var a,b,c=this;for(b=0;a=x[b];b++)this[a[0]]="function"==typeof a[1]?a[1].apply(this):a[1];for(b=0;a=y[b];b++)Object.defineProperty(c,a[0],{enumerable:!0,get:a[1]})}},h,i,l),p(B.prototype,{$type:r,$new:function(a,b){return r.$new(a,b||this)},$collection:function(b,c){return b=this.$params?a.extend({},this.$params,b):b,s(b,c||this.$scope)}},j,g,h,k,l),p(C.prototype,{$type:r},j,h),p(D.prototype,{$type:r,$initialize:function(){}},h);var E={Model:r,Record:r.prototype,Collection:B.prototype,List:C.prototype,Dummy:D.prototype};return u=new n(a.extend(w.dsl(),{setProperty:function(a,b){return v[a]=b,this},attrDefault:function(a,b){return x.push([a,b]),this},attrComputed:function(a,b){return y.push([a,b]),this.attrMask(a,!0),this},attrMeta:function(a,b){return z[a]=p(z[a]||{},b),this},define:function(a,b){var c=!1,d="Record";switch("object"==typeof b&&b?d=a:(c=a.split("."),1===c.length?c=c[0]:(d=c[0],c=c[1])),d){case"List":t("Collection",c,b),t("List",c,b);break;case"Scope":t("Model",c,b),t("Collection",c,b);break;case"Resource":t("Record",c,b),t("Collection",c,b),t("List",c,b),t("Dummy",c,b);break;default:t(d,c,b)}return this},on:function(a,b){return(A[a]||(A[a]=[])).push(b),this}})),u.chain(q),r}}]),c.factory("RMFastQ",[function(){function b(a,f){return a&&d(a.then)?c(a):{simple:!0,then:function(c,d){return b(f?d(a):c(a))},"catch":e,"finally":function(e){var g=e();return g&&d(a.then)?c(a.then(function(){return f?b(a,!0):a},function(){return f?b(a,!0):a})):this}}}function c(a){if(a.simple)return a;var d;return a.then(function(a){d=b(a)},function(a){d=b(a,!0)}),{then:function(b,e){return d?d.then(b,e):c(a.then(b,e))},"catch":e,"finally":function(b){return d?d["finally"](b):c(a["finally"](b))}}}var d=a.isFunction,e=function(a){return this.then(null,a)};return{reject:function(a){return b(a,!0)},when:function(a){return b(a,!1)},wrap:c}}]),c.factory("RMPackerCache",[function(){var a;return{feed:function(b,c){a[b]=c},resolve:function(b){if(a){var c=b.$type,d=a[c.identity(!0)];if(d&&b.$pk)for(var e=0,f=d.length;f>e;e++)if(b.$pk===c.inferKey(d[e])){b.$decode(d[e]);break}}return b},prepare:function(){a={}},clear:function(){a=null}}}]),c.factory("RMSerializer",["$injector","inflector","$filter","RMUtils",function(c,d,e,f){function g(a,b){for(var c,d=0;a&&(c=b[d]);d++)a=a[c];return a}function h(a,b,c){for(var d=0,e=b.length-1;e>d;d++){var f=b[d];a=a[f]||(a[f]={})}a[b[b.length-1]]=c}return function(c){function d(a,b){if("function"==typeof b)return b(a);var c=n[a];return c&&(c===!0||-1!==c.indexOf(b))}function i(a,e,f,h,i){var k,l,m,n,o,p,s,t,u=f?f+".":"";if(o=r[f])for(s=0,t=o.length;t>s;s++)m=u+o[s].path,d(m,h)||(n=o[s].map?g(a,o[s].map):a[c.encodeName?c.encodeName(o[s].path):o[s].path],(o[s].forced||n!==b)&&(n=j(n,m,h,i),n!==b&&(e[o[s].path]=n)));for(k in a)if(a.hasOwnProperty(k)){if(l=c.decodeName?c.decodeName(k):k,"$"===l[0])continue;if(o){for(p=!1,s=0,t=o.length;t>s&&!(p=o[s].mapPath===k);s++);if(p)continue}if(m=u+l,q[m]||d(m,h))continue;n=j(a[k],m,h,i),n!==b&&(e[l]=n)}}function j(a,b,c,d){var e=o[b],f=a;if(e)f=e.call(d,a);else if("object"==typeof a)if(m(a)){f=[];for(var g=0,h=a.length;h>g;g++)f.push(j(a[g],b+"[]",c,d))}else a&&(f={},i(a,f,b,c,d));return f}function k(a,e,f,g,i){var j,k,m,n,o,p=f?f+".":"";for(j in a)if(a.hasOwnProperty(j)&&"$"!==j[0]){if(k=p+j,q[k]||d(k,g))continue;n=l(a[j],k,g,i),n!==b&&(m=c.encodeName?c.encodeName(j):j,e[m]=n),s[k]&&delete a[j]}if(o=r[f])for(var t=0,u=o.length;u>t;t++)k=p+o[t].path,d(k,g)||(n=a[o[t].path],(o[t].forced||n!==b)&&(n=l(n,k,g,i),n!==b&&(o[t].map?h(e,o[t].map,n):e[c.encodeName?c.encodeName(o[t].path):o[t].path]=n)))}function l(a,b,c,d){var e=p[b],f=a;if(e)f=e.call(d,a);else if(null!==a&&"object"==typeof a&&"function"!=typeof a.toJSON)if(m(a)){f=[];for(var g=0,h=a.length;h>g;g++)f.push(l(a[g],b+"[]",c,d))}else a&&(f={},k(a,f,b,c,d));return f}var m=a.isArray,n={},o={},p={},q={},r={},s={};return{decode:function(a,b,c){i(b,a,"",c,a)},encode:function(a,b){var c={};return k(a,c,"",b,a),c},dsl:function(){return{attrMap:function(a,b,c){var d=a.lastIndexOf("."),e=-1!==d?a.substr(0,d):"",f=-1!==d?a.substr(d+1):a;q[a]=!0;var g=r[e]||(r[e]=[]);return g.push({path:f,map:"*"===b?null:b.split("."),mapPath:b,forced:c}),this},attrMask:function(a,b){return b?n[a]=b:delete n[a],this},attrDecoder:function(a,b,c,d){if("string"==typeof b){var g=e(b);b=function(a){return g(a,c)}}return o[a]=d?f.chain(o[a],b):b,this},attrEncoder:function(a,b,c,d){if("string"==typeof b){var g=e(b);b=function(a){return g(a,c)}}return p[a]=d?f.chain(p[a],b):b,this},attrVolatile:function(a,c){return s[a]=c===b?!0:c,this}}}}}}]),c.factory("DefaultPacker",["restmod","inflector","RMPackerCache",function(b,c,d){function e(a,b,c){for(var d=0,e=b.length;e>d;d++)c(b[d],a[b[d]])}function f(a,b,c){for(var d in a)a.hasOwnProperty(d)&&-1===b.indexOf(d)&&c(d,a[d])}function g(b,c,d,g,h){if("."===d||d===!0){var i=[c];g&&i.push.apply(i,a.isArray(g)?g:[g]),f(b,i,h)}else"string"==typeof d?f(b[d],[],h):e(b,d,h)}return b.mixin(function(){this.define("Model.unpack",function(a,b){var c=null,e=this.getProperty("jsonLinks","linked"),f=this.getProperty("jsonMeta","meta");return c=a.$isCollection?this.getProperty("jsonRootMany")||this.getProperty("jsonRoot")||this.getProperty("plural"):this.getProperty("jsonRootSingle")||this.getProperty("jsonRoot")||this.getProperty("name"),f&&(a.$metadata={},g(b,c,f,e,function(b,c){a.$metadata[b]=c})),e&&g(b,c,e,f,function(a,b){d.feed(a,b)}),b[c]})})}]),c.factory("RMUtils",["$log",function(a){var b=[],c=function(){var a=function(){};return Object.setPrototypeOf?function(a,b){Object.setPrototypeOf(a,b)}:(new a).__proto__===a.prototype?function(a,b){a.__proto__=b}:void 0}(),d={CREATE_MASK:"C",UPDATE_MASK:"U",READ_MASK:"R",WRITE_MASK:"CU",FULL_MASK:"CRU",format:function(a,b){for(var c=0;b&&cparent.RestmodArray = Array;"),d=window.RestmodArray,delete window.RestmodArray;for(var g in Array.prototype)"function"!=typeof Array.prototype[g]||d.prototype[g]||(d.prototype[g]=Array.prototype[g]);document.body.removeChild(f),b.push(f)}return d}};return d}])}(angular);
\ No newline at end of file
diff --git a/dist/plugins/debounced.js b/dist/plugins/debounced.js
index 6e997e4..191e399 100644
--- a/dist/plugins/debounced.js
+++ b/dist/plugins/debounced.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/debounced.min.js b/dist/plugins/debounced.min.js
index 5e95f00..5379d09 100644
--- a/dist/plugins/debounced.min.js
+++ b/dist/plugins/debounced.min.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/dirty.js b/dist/plugins/dirty.js
index 66b6f23..7231e11 100644
--- a/dist/plugins/dirty.js
+++ b/dist/plugins/dirty.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/dirty.min.js b/dist/plugins/dirty.min.js
index 04489ee..7e47ed5 100644
--- a/dist/plugins/dirty.min.js
+++ b/dist/plugins/dirty.min.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/find-many.js b/dist/plugins/find-many.js
index 998c198..a564c52 100644
--- a/dist/plugins/find-many.js
+++ b/dist/plugins/find-many.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/find-many.min.js b/dist/plugins/find-many.min.js
index 978e863..d9621dd 100644
--- a/dist/plugins/find-many.min.js
+++ b/dist/plugins/find-many.min.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/nested-dirty.js b/dist/plugins/nested-dirty.js
new file mode 100644
index 0000000..ade69d7
--- /dev/null
+++ b/dist/plugins/nested-dirty.js
@@ -0,0 +1,172 @@
+/**
+ * API Bound Models for AngularJS
+ * @version v1.1.6 - 2015-01-06
+ * @link https://github.com/angular-platanus/restmod
+ * @author Ignacio Baixas
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+
+(function(angular, undefined) {
+'use strict';
+/**
+ * @mixin NestedDirtyModel
+ *
+ * @description Adds the `$dirty` method to a model`s instances. Acts in the same way as the DirtyModel plugin, but supports nested objects.
+ */
+
+angular.module('restmod').factory('NestedDirtyModel', ['restmod', function(restmod) {
+
+ function isPlainObject(_val) {
+ return angular.isObject(_val) && !angular.isArray(_val);
+ }
+
+ function copyOriginalData(_from) {
+ var Model = _from.$type, result = {};
+
+ _from.$each(function(value, key) {
+ var meta = Model.$$getDescription(key);
+ if(!meta || !meta.relation) {
+ // TODO: skip masked properties too?
+ result[key] = angular.copy(value);
+ }
+ });
+
+ return result;
+ }
+
+ function navigate(_target, _keys) {
+ var key, i = 0;
+ while((key = _keys[i++])) {
+ if(_target) {
+ _target = _target.hasOwnProperty(key) ? _target[key] : null;
+ }
+ }
+ return _target;
+ }
+
+ function hasValueChanged(_model, _original, _keys, _comparator) {
+ var prop = _keys.pop();
+
+ _model = navigate(_model, _keys);
+ _original = navigate(_original, _keys);
+
+ if(angular.isObject(_original) && angular.isObject(_model) && _original.hasOwnProperty(prop)) {
+ if(typeof _comparator === 'function') {
+ return !!_comparator(_model[prop], _original[prop]);
+ } else {
+ return !angular.equals(_model[prop], _original[prop]);
+ }
+ }
+
+ return false;
+ }
+
+ function findChangedValues(_model, _original, _keys, _comparator) {
+ var changes = [], childChanges;
+
+ if(_original) {
+ for(var key in _original) {
+ if(_original.hasOwnProperty(key)) {
+ if(isPlainObject(_original[key]) && isPlainObject(_model[key])) {
+ childChanges = findChangedValues(_model[key], _original[key], _keys.concat([key]), _comparator);
+ changes.push.apply(changes, childChanges);
+ } else if(hasValueChanged(_model, _original, [key], _comparator)) {
+ changes.push(_keys.concat([key]));
+ }
+ }
+ }
+ }
+
+ return changes;
+ }
+
+ function changesAsStrings(_changes) {
+ for(var i = 0, l = _changes.length; i < l; i++) {
+ _changes[i] = _changes[i].join('.');
+ }
+ return _changes;
+ }
+
+ function restoreValue(_model, _original, _keys) {
+ var prop = _keys.pop();
+ _model = navigate(_model, _keys);
+ _original = navigate(_original, _keys);
+
+ if(_original && _model && _original.hasOwnProperty(prop)) {
+ _model[prop] = angular.copy(_original[prop]);
+ }
+ }
+
+ return restmod.mixin(function() {
+ this.on('after-feed', function() {
+ // store original information in a model's special property
+ this.$cmStatus = copyOriginalData(this);
+ })
+ /**
+ * @method $dirty
+ * @memberof NestedDirtyModel#
+ *
+ * @description Retrieves the model changes
+ *
+ * Property changes are determined using the strict equality operator if no comparator
+ * function is provided.
+ *
+ * If given a property name, this method will return true if property has changed
+ * or false if it has not.
+ *
+ * The comparator function can be passed either as the first or second parameter.
+ * If first, this function will compare all properties using the comparator.
+ *
+ * Called without arguments, this method will return a list of changed property names.
+ *
+ * @param {string|function} _prop Property to query or function to compare all properties
+ * @param {function} _comparator Function to compare property
+ * @return {boolean|array} Property state or array of changed properties
+ */
+ .define('$dirty', function(_prop, _comparator) {
+ var original = this.$cmStatus;
+
+ if(_prop && !angular.isFunction(_prop)) {
+ return hasValueChanged(this, original, _prop.split('.'), _comparator);
+ } else {
+ if(angular.isFunction(_prop)) _comparator = _prop;
+ return changesAsStrings(findChangedValues(this, original, [], _comparator));
+ }
+ })
+ /**
+ * @method $restore
+ * @memberof NestedDirtyModel#
+ *
+ * @description Restores the model's last fetched values.
+ *
+ * Usage:
+ *
+ * ```javascript
+ * bike = Bike.$create({ brand: 'Trek' });
+ * // later on...
+ * bike.brand = 'Giant';
+ * bike.$restore();
+ *
+ * console.log(bike.brand); // outputs 'Trek'
+ * ```
+ *
+ * @param {string} _prop If provided, only _prop is restored
+ * @return {Model} self
+ */
+ .define('$restore', function(_prop) {
+ return this.$action(function() {
+ var original = this.$cmStatus;
+
+ if(_prop) {
+ var keys = _prop.split('.');
+ restoreValue(this, original, keys);
+ } else {
+ var changes = findChangedValues(this, original, []);
+ for(var i = 0, l = changes.length; i < l; i++) {
+ restoreValue(this, original, changes[i]);
+ }
+ }
+ });
+ });
+ });
+}]);})(angular);
\ No newline at end of file
diff --git a/dist/plugins/nested-dirty.min.js b/dist/plugins/nested-dirty.min.js
new file mode 100644
index 0000000..faaf61a
--- /dev/null
+++ b/dist/plugins/nested-dirty.min.js
@@ -0,0 +1,8 @@
+/**
+ * API Bound Models for AngularJS
+ * @version v1.1.6 - 2015-01-06
+ * @link https://github.com/angular-platanus/restmod
+ * @author Ignacio Baixas
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+!function(a){"use strict";a.module("restmod").factory("NestedDirtyModel",["restmod",function(b){function c(b){return a.isObject(b)&&!a.isArray(b)}function d(b){var c=b.$type,d={};return b.$each(function(b,e){var f=c.$$getDescription(e);f&&f.relation||(d[e]=a.copy(b))}),d}function e(a,b){for(var c,d=0;c=b[d++];)a&&(a=a.hasOwnProperty(c)?a[c]:null);return a}function f(b,c,d,f){var g=d.pop();return b=e(b,d),c=e(c,d),a.isObject(c)&&a.isObject(b)&&c.hasOwnProperty(g)?"function"==typeof f?!!f(b[g],c[g]):!a.equals(b[g],c[g]):!1}function g(a,b,d,e){var h,i=[];if(b)for(var j in b)b.hasOwnProperty(j)&&(c(b[j])&&c(a[j])?(h=g(a[j],b[j],d.concat([j]),e),i.push.apply(i,h)):f(a,b,[j],e)&&i.push(d.concat([j])));return i}function h(a){for(var b=0,c=a.length;c>b;b++)a[b]=a[b].join(".");return a}function i(b,c,d){var f=d.pop();b=e(b,d),c=e(c,d),c&&b&&c.hasOwnProperty(f)&&(b[f]=a.copy(c[f]))}return b.mixin(function(){this.on("after-feed",function(){this.$cmStatus=d(this)}).define("$dirty",function(b,c){var d=this.$cmStatus;return b&&!a.isFunction(b)?f(this,d,b.split("."),c):(a.isFunction(b)&&(c=b),h(g(this,d,[],c)))}).define("$restore",function(a){return this.$action(function(){var b=this.$cmStatus;if(a){var c=a.split(".");i(this,b,c)}else for(var d=g(this,b,[]),e=0,f=d.length;f>e;e++)i(this,b,d[e])})})})}])}(angular);
\ No newline at end of file
diff --git a/dist/plugins/paged.js b/dist/plugins/paged.js
index e08039b..1ba6a55 100644
--- a/dist/plugins/paged.js
+++ b/dist/plugins/paged.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/paged.min.js b/dist/plugins/paged.min.js
index 65cbd49..aa78674 100644
--- a/dist/plugins/paged.min.js
+++ b/dist/plugins/paged.min.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/preload.js b/dist/plugins/preload.js
index 78c7bde..9c7e200 100644
--- a/dist/plugins/preload.js
+++ b/dist/plugins/preload.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/plugins/preload.min.js b/dist/plugins/preload.min.js
index 04d278a..9528bd6 100644
--- a/dist/plugins/preload.min.js
+++ b/dist/plugins/preload.min.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/styles/ams.js b/dist/styles/ams.js
index a81ad39..e82e64f 100644
--- a/dist/styles/ams.js
+++ b/dist/styles/ams.js
@@ -1,6 +1,6 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -23,7 +23,8 @@ angular.module('restmod').factory('AMSApi', ['restmod', 'inflector', function(re
// special snakecase to camelcase renaming
Model: {
decodeName: inflector.camelize,
- encodeName: function(_v) { return inflector.parameterize(_v, '_'); }
+ encodeName: function(_v) { return inflector.parameterize(_v, '_'); },
+ encodeUrlName: inflector.parameterize
}
}
});
diff --git a/dist/styles/ams.min.js b/dist/styles/ams.min.js
index 66f3905..f70ca1b 100644
--- a/dist/styles/ams.min.js
+++ b/dist/styles/ams.min.js
@@ -1,8 +1,8 @@
/**
* API Bound Models for AngularJS
- * @version v1.1.5 - 2014-12-10
+ * @version v1.1.6 - 2015-01-06
* @link https://github.com/angular-platanus/restmod
* @author Ignacio Baixas
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-!function(a){"use strict";a.module("restmod").factory("AMSApi",["restmod","inflector",function(a,b){return a.mixin("DefaultPacker",{$config:{style:"AMS",primaryKey:"id",jsonMeta:"meta",jsonLinks:"links"},$extend:{Model:{decodeName:b.camelize,encodeName:function(a){return b.parameterize(a,"_")}}}})}])}(angular);
\ No newline at end of file
+!function(a){"use strict";a.module("restmod").factory("AMSApi",["restmod","inflector",function(a,b){return a.mixin("DefaultPacker",{$config:{style:"AMS",primaryKey:"id",jsonMeta:"meta",jsonLinks:"links"},$extend:{Model:{decodeName:b.camelize,encodeName:function(a){return b.parameterize(a,"_")},encodeUrlName:b.parameterize}}})}])}(angular);
\ No newline at end of file
diff --git a/package.json b/package.json
index 3262f52..a0275b6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "angular-restmod",
- "version": "1.1.5",
+ "version": "1.1.6",
"engines": {
"node": ">= 0.9"
},