angularjs-rails-resource 0.2.5 → 1.0.0.pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * A resource factory inspired by $resource from AngularJS
3
- * @version v0.2.5 - 2013-11-24
3
+ * @version v1.0.0-pre1 - 2013-10-06
4
4
  * @link https://github.com/FineLinePrototyping/angularjs-rails-resource.git
5
5
  * @author
6
6
  */
7
- !function(){angular.module("rails",["ng"])}(),function(){angular.module("rails").factory("RailsInflector",function(){function a(a){return angular.isString(a)?a.replace(/_[\w\d]/g,function(a,b,c){return 0===b?a:c.charAt(b+1).toUpperCase()}):a}function b(a){return angular.isString(a)?a.replace(/[A-Z]/g,function(a,b){return 0===b?a:"_"+a.toLowerCase()}):a}function c(a){return a+"s"}return{camelize:a,underscore:b,pluralize:c}})}(),function(a){angular.module("rails").factory("RailsResourceInjector",["$injector",function(b){function c(c){return c?angular.isString(c)?b.get(c):c:a}function d(d){return d?b.instantiate(c(d)):a}return{createService:d,getDependency:c}}])}(),function(){angular.module("rails").factory("railsUrlBuilder",["$interpolate",function(a){return function(b){var c;return angular.isFunction(b)?b:(-1===b.indexOf(a.startSymbol())&&(b=b+"/"+a.startSymbol()+"id"+a.endSymbol()),c=a(b),function(a){return b=c(a),"/"===b.charAt(b.length-1)&&(b=b.substr(0,b.length-1)),b})}}])}(),function(a){angular.module("rails").provider("railsSerializer",function(){var b={underscore:a,camelize:a,pluralize:a,exclusionMatchers:[]};this.underscore=function(a){return b.underscore=a,this},this.camelize=function(a){return b.camelize=a,this},this.pluralize=function(a){return b.pluralize=a,this},this.exclusionMatchers=function(a){return b.exclusionMatchers=a,this},this.$get=["$injector","RailsInflector","RailsResourceInjector",function(c,d,e){function f(c,d){function f(){angular.isFunction(c)&&(d=c,c={}),this.exclusions={},this.inclusions={},this.serializeMappings={},this.deserializeMappings={},this.customSerializedAttributes={},this.preservedAttributes={},this.customSerializers={},this.nestedResources={},this.options=angular.extend({excludeByDefault:!1},b,c||{}),d&&d.call(this,this)}return f.prototype.exclude=function(){var a=this.exclusions;return angular.forEach(arguments,function(b){a[b]=!1}),this},f.prototype.only=function(){var a=this.inclusions;return this.options.excludeByDefault=!0,angular.forEach(arguments,function(b){a[b]=!0}),this},f.prototype.nestedAttribute=function(){var a=this;return angular.forEach(arguments,function(b){a.rename(b,b+"_attributes")}),this},f.prototype.resource=function(a,b,c){return this.nestedResources[a]=b,c&&this.serializeWith(a,c),this},f.prototype.rename=function(b,c,d){return this.serializeMappings[b]=c,(d||d===a)&&(this.deserializeMappings[c]=b),this},f.prototype.add=function(a,b){return this.customSerializedAttributes[a]=b,this},f.prototype.preserve=function(a){return this.preservedAttributes[a]=!0,this},f.prototype.serializeWith=function(a,b){return this.customSerializers[a]=b,this},f.prototype.isExcludedFromSerialization=function(b){if(this.options.excludeByDefault&&!this.inclusions.hasOwnProperty(b)||this.exclusions.hasOwnProperty(b))return!0;if(this.options.exclusionMatchers){var c=!1;return angular.forEach(this.options.exclusionMatchers,function(d){angular.isString(d)?c=c||0===b.indexOf(d):angular.isFunction(d)?c=c||d.call(a,b):d instanceof RegExp&&(c=c||d.test(b))}),c}return!1},f.prototype.getSerializedAttributeName=function(b){var c=this.serializeMappings[b]||b,d=this.isExcludedFromSerialization(c),e=this.isExcludedFromSerialization(b);if(this.options.excludeByDefault){if(d&&e)return a}else if(d||e)return a;return this.underscore(c)},f.prototype.isExcludedFromDeserialization=function(){return!1},f.prototype.getDeserializedAttributeName=function(b){var c=this.camelize(b);return c=this.deserializeMappings[b]||this.deserializeMappings[c]||c,this.isExcludedFromDeserialization(b)||this.isExcludedFromDeserialization(c)?a:c},f.prototype.getNestedResource=function(a){return e.getDependency(this.nestedResources[a])},f.prototype.getAttributeSerializer=function(b){var c=this.getNestedResource(b),d=this.customSerializers[b];return d?e.createService(d):c?c.serializer:a},f.prototype.serializeValue=function(a){var b=a,c=this;if(angular.isArray(a))b=[],angular.forEach(a,function(a){b.push(c.serializeValue(a))});else if(angular.isObject(a)){if(angular.isDate(a))return a;b={},angular.forEach(a,function(a,d){angular.isFunction(a)||c.serializeAttribute(b,d,a)})}return b},f.prototype.serializeAttribute=function(b,c,d){var e=this.getAttributeSerializer(c),f=this.getSerializedAttributeName(c);f!==a&&(b[f]=e?e.serialize(d):this.serializeValue(d))},f.prototype.serialize=function(a){var b=this.serializeValue(a),c=this;return angular.isObject(b)&&angular.forEach(this.customSerializedAttributes,function(d,e){angular.isFunction(d)&&(d=d.call(a,a)),c.serializeAttribute(b,e,d)}),b},f.prototype.deserializeValue=function(a,b){var c=a,d=this;if(angular.isArray(a))c=[],angular.forEach(a,function(a){c.push(d.deserializeValue(a,b))});else if(angular.isObject(a)){if(angular.isDate(a))return a;c={},b&&(c=new b),angular.forEach(a,function(a,b){d.deserializeAttribute(c,b,a)})}return c},f.prototype.deserializeAttribute=function(b,c,d){var e,f,g=this.getDeserializedAttributeName(c);g!==a&&(e=this.getAttributeSerializer(g),f=this.getNestedResource(g),b[g]=this.preservedAttributes[g]?d:e?e.deserialize(d,f):this.deserializeValue(d,f))},f.prototype.deserialize=function(a,b){return this.deserializeValue(a,b)},f.prototype.pluralize=function(a){return this.options.pluralize?this.options.pluralize(a):a},f.prototype.underscore=function(a){return this.options.underscore?this.options.underscore(a):a},f.prototype.camelize=function(a){return this.options.camelize?this.options.camelize(a):a},f}return b.underscore=b.underscore||d.underscore,b.camelize=b.camelize||d.camelize,b.pluralize=b.pluralize||d.pluralize,f.defaultOptions=b,f}]})}(),function(a){angular.module("rails").factory("railsRootWrappingTransformer",function(){return function(a,b){var c={};return c[angular.isArray(a)?b.rootPluralName:b.rootName]=a,c}}),angular.module("rails").factory("railsRootWrappingInterceptor",function(){return function(a){var b=a.resource;return b?a.then(function(a){return a.data&&a.data.hasOwnProperty(b.rootName)?a.data=a.data[b.rootName]:a.data&&a.data.hasOwnProperty(b.rootPluralName)&&(a.data=a.data[b.rootPluralName]),a}):a}}),angular.module("rails").provider("railsResourceFactory",function(){var b={enableRootWrapping:!0,updateMethod:"put",httpConfig:{},defaultParams:a};this.enableRootWrapping=function(a){return b.enableRootWrapping=a,this},this.updateMethod=function(a){return b.updateMethod=a,this},this.httpConfig=function(a){return b.httpConfig=a,this},this.defaultParams=function(a){return b.defaultParams=a,this},this.$get=["$http","$q","railsUrlBuilder","railsSerializer","railsRootWrappingTransformer","railsRootWrappingInterceptor","RailsResourceInjector",function(c,d,e,f,g,h,i){function j(d){function j(a,b){return b&&("/"!==b[0]&&(a+="/"),a+=b),a}function k(a){var b=this;if(a){var c=function(a){return{resource:k,context:b,response:a,then:function(a){return this.response=a(this.response,this.resource,this.context),c(this.response)}}},d=k.callInterceptors(c({data:a}),this).response.data;angular.extend(this,d)}}var l=d.requestTransformers,m=d.responseInterceptors,n=d.afterResponseInterceptors;return k.setUrl=function(a){k.url=e(a)},k.setUrl(d.url),k.enableRootWrapping=d.wrapData===a?b.enableRootWrapping:d.wrapData,k.httpConfig=d.httpConfig||b.httpConfig,k.httpConfig.headers=angular.extend({Accept:"application/json","Content-Type":"application/json"},k.httpConfig.headers||{}),k.defaultParams=d.defaultParams||b.defaultParams,k.updateMethod=(d.updateMethod||b.updateMethod).toLowerCase(),k.requestTransformers=[],k.responseInterceptors=[],k.afterResponseInterceptors=[],k.serializer=i.createService(d.serializer||f()),k.rootName=k.serializer.underscore(d.name),k.rootPluralName=k.serializer.underscore(d.pluralName||k.serializer.pluralize(d.name)),k.beforeResponse=function(a){a=i.getDependency(a),k.responseInterceptors.push(function(b){return b.then(function(c){return a(c.data,b.resource,b.context),c})})},k.afterResponse=function(a){a=i.getDependency(a),k.afterResponseInterceptors.push(function(b){return b.then(function(c){return a(c,b.resource),c})})},k.beforeRequest=function(a){a=i.getDependency(a),k.requestTransformers.push(function(b,c){return a(b,c)||b})},angular.forEach(m,function(a){k.responseInterceptors.push(i.getDependency(a))}),angular.forEach(n,function(a){k.afterResponseInterceptors.push(i.getDependency(a))}),angular.forEach(l,function(a){k.requestTransformers.push(i.getDependency(a))}),k.transformData=function(a){return a=k.serializer.serialize(a),angular.forEach(k.requestTransformers,function(b){a=b(a,k)}),k.enableRootWrapping&&(a=g(a,k)),a},k.callInterceptors=function(a,b){return a=a.then(function(a){return a.originalData=a.data,a}),k.enableRootWrapping&&(a.resource=k,a=h(a)),a.then(function(a){return a.data=k.serializer.deserialize(a.data,k),a}),angular.forEach(k.responseInterceptors,function(c){a.resource=k,a.context=b,a=c(a)}),a},k.callAfterInterceptors=function(a){return angular.forEach(k.afterResponseInterceptors,function(b){a.resource=k,a=b(a)}),a},k.processResponse=function(a){return a=k.callInterceptors(a).then(function(a){return a.data}),k.callAfterInterceptors(a)},k.getParameters=function(a){var b;return k.defaultParams&&(b=k.defaultParams),angular.isObject(a)&&(b=angular.extend(b||{},a)),b},k.getHttpConfig=function(a){var b=k.getParameters(a);return b?angular.extend({params:b},k.httpConfig):angular.copy(k.httpConfig)},k.$url=k.resourceUrl=function(a,b){return angular.isObject(a)||(a={id:a}),j(k.url(a||{}),b)},k.$get=function(a,b){return k.processResponse(c.get(a,k.getHttpConfig(b)))},k.query=function(a,b){return k.$get(k.resourceUrl(b),a)},k.get=function(a,b){return k.$get(k.resourceUrl(a),b)},k.prototype.$url=function(a){return j(k.resourceUrl(this),a)},k.prototype.processResponse=function(a){return a=k.callInterceptors(a,this),a=a.then(angular.bind(this,function(a){return a.hasOwnProperty("data")&&angular.isObject(a.data)&&angular.extend(this,a.data),this})),k.callAfterInterceptors(a)},angular.forEach(["post","put","patch"],function(a){k["$"+a]=function(b,d){var e;return d=k.transformData(angular.copy(d)),e=angular.extend({method:a,url:b,data:d},k.getHttpConfig()),k.processResponse(c(e))},k.prototype["$"+a]=function(b){var d,e;return d=k.transformData(angular.copy(this,{})),e=angular.extend({method:a,url:b,data:d},k.getHttpConfig()),this.processResponse(c(e))}}),k.prototype.create=function(){return this.$post(this.$url(),this)},k.prototype.update=function(){return this["$"+k.updateMethod](this.$url(),this)},k.prototype.isNew=function(){return null==this.id},k.prototype.save=function(){return this.isNew()?this.create():this.update()},k.$delete=function(a){return k.processResponse(c["delete"](a,k.getHttpConfig()))},k.prototype.$delete=function(a){return this.processResponse(c["delete"](a,k.getHttpConfig()))},k.prototype.remove=k.prototype["delete"]=function(){return this.$delete(this.$url())},k}return j}]})}();
7
+ !function(){angular.module("rails",["ng"])}(),function(){angular.module("rails").factory("RailsInflector",function(){function a(a){return angular.isString(a)?a.replace(/_[\w\d]/g,function(a,b,c){return 0===b?a:c.charAt(b+1).toUpperCase()}):a}function b(a){return angular.isString(a)?a.replace(/[A-Z]/g,function(a,b){return 0===b?a:"_"+a.toLowerCase()}):a}function c(a){return a+"s"}return{camelize:a,underscore:b,pluralize:c}})}(),function(a){angular.module("rails").factory("RailsResourceInjector",["$injector",function(b){function c(c){return c?angular.isString(c)?b.get(c):c:a}function d(d){return d?b.instantiate(c(d)):a}return{createService:d,getDependency:c}}])}(),function(){angular.module("rails").factory("railsUrlBuilder",["$interpolate",function(a){return function(b){var c;return angular.isFunction(b)||angular.isUndefined(b)?b:(-1===b.indexOf(a.startSymbol())&&(b=b+"/"+a.startSymbol()+"id"+a.endSymbol()),c=a(b),function(a){return b=c(a),"/"===b.charAt(b.length-1)&&(b=b.substr(0,b.length-1)),b})}}])}(),function(a){angular.module("rails").provider("railsSerializer",function(){var b={underscore:a,camelize:a,pluralize:a,exclusionMatchers:[]};this.underscore=function(a){return b.underscore=a,this},this.camelize=function(a){return b.camelize=a,this},this.pluralize=function(a){return b.pluralize=a,this},this.exclusionMatchers=function(a){return b.exclusionMatchers=a,this},this.$get=["$injector","RailsInflector","RailsResourceInjector",function(c,d,e){function f(c,d){function f(){angular.isFunction(c)&&(d=c,c={}),this.exclusions={},this.inclusions={},this.serializeMappings={},this.deserializeMappings={},this.customSerializedAttributes={},this.preservedAttributes={},this.customSerializers={},this.nestedResources={},this.options=angular.extend({excludeByDefault:!1},b,c||{}),d&&d.call(this,this)}return f.prototype.exclude=function(){var a=this.exclusions;return angular.forEach(arguments,function(b){a[b]=!1}),this},f.prototype.only=function(){var a=this.inclusions;return this.options.excludeByDefault=!0,angular.forEach(arguments,function(b){a[b]=!0}),this},f.prototype.nestedAttribute=function(){var a=this;return angular.forEach(arguments,function(b){a.rename(b,b+"_attributes")}),this},f.prototype.resource=function(a,b,c){return this.nestedResources[a]=b,c&&this.serializeWith(a,c),this},f.prototype.rename=function(b,c,d){return this.serializeMappings[b]=c,(d||d===a)&&(this.deserializeMappings[c]=b),this},f.prototype.add=function(a,b){return this.customSerializedAttributes[a]=b,this},f.prototype.preserve=function(a){return this.preservedAttributes[a]=!0,this},f.prototype.serializeWith=function(a,b){return this.customSerializers[a]=b,this},f.prototype.isExcludedFromSerialization=function(b){if(this.options.excludeByDefault&&!this.inclusions.hasOwnProperty(b)||this.exclusions.hasOwnProperty(b))return!0;if(this.options.exclusionMatchers){var c=!1;return angular.forEach(this.options.exclusionMatchers,function(d){angular.isString(d)?c=c||0===b.indexOf(d):angular.isFunction(d)?c=c||d.call(a,b):d instanceof RegExp&&(c=c||d.test(b))}),c}return!1},f.prototype.getSerializedAttributeName=function(b){var c=this.serializeMappings[b]||b;return this.isExcludedFromSerialization(b)||this.isExcludedFromSerialization(c)?a:this.underscore(c)},f.prototype.isExcludedFromDeserialization=function(){return!1},f.prototype.getDeserializedAttributeName=function(b){var c=this.camelize(b);return c=this.deserializeMappings[b]||this.deserializeMappings[c]||c,this.isExcludedFromDeserialization(b)||this.isExcludedFromDeserialization(c)?a:c},f.prototype.getNestedResource=function(a){return e.getDependency(this.nestedResources[a])},f.prototype.getAttributeSerializer=function(b){var c=this.getNestedResource(b),d=this.customSerializers[b];return d?e.createService(d):c?c.config.serializer:a},f.prototype.serializeValue=function(a){var b=a,c=this;if(angular.isArray(a))b=[],angular.forEach(a,function(a){b.push(c.serializeValue(a))});else if(angular.isObject(a)){if(angular.isDate(a))return a;b={},angular.forEach(a,function(a,d){angular.isFunction(a)||c.serializeAttribute(b,d,a)})}return b},f.prototype.serializeAttribute=function(b,c,d){var e=this.getAttributeSerializer(c),f=this.getSerializedAttributeName(c);f!==a&&(b[f]=e?e.serialize(d):this.serializeValue(d))},f.prototype.serialize=function(a){var b=this.serializeValue(a),c=this;return angular.isObject(b)&&angular.forEach(this.customSerializedAttributes,function(d,e){angular.isFunction(d)&&(d=d.call(a,a)),c.serializeAttribute(b,e,d)}),b},f.prototype.deserializeValue=function(a,b){var c=a,d=this;if(angular.isArray(a))c=[],angular.forEach(a,function(a){c.push(d.deserializeValue(a,b))});else if(angular.isObject(a)){if(angular.isDate(a))return a;c={},b&&(c=new b.config.resourceConstructor),angular.forEach(a,function(a,b){d.deserializeAttribute(c,b,a)})}return c},f.prototype.deserializeAttribute=function(b,c,d){var e,f,g=this.getDeserializedAttributeName(c);g!==a&&(e=this.getAttributeSerializer(g),f=this.getNestedResource(g),b[g]=this.preservedAttributes[g]?d:e?e.deserialize(d,f):this.deserializeValue(d,f))},f.prototype.deserialize=function(a,b){return this.deserializeValue(a,b)},f.prototype.pluralize=function(a){return this.options.pluralize?this.options.pluralize(a):a},f.prototype.underscore=function(a){return this.options.underscore?this.options.underscore(a):a},f.prototype.camelize=function(a){return this.options.camelize?this.options.camelize(a):a},f}return b.underscore=b.underscore||d.underscore,b.camelize=b.camelize||d.camelize,b.pluralize=b.pluralize||d.pluralize,f.defaultOptions=b,f}]})}(),function(a){angular.module("rails").factory("railsRootWrappingTransformer",function(){return function(a,b){var c={};return c[angular.isArray(a)?b.config.pluralName:b.config.name]=a,c}}),angular.module("rails").factory("railsRootWrappingInterceptor",function(){return function(a){var b=a.resource;return b?a.then(function(a){return a.data&&a.data.hasOwnProperty(b.config.name)?a.data=a.data[b.config.name]:a.data&&a.data.hasOwnProperty(b.config.pluralName)&&(a.data=a.data[b.config.pluralName]),a}):a}}),angular.module("rails").provider("RailsResource",function(){var b={rootWrapping:!0,updateMethod:"put",httpConfig:{},defaultParams:a};this.rootWrapping=function(a){return b.rootWrapping=a,this},this.updateMethod=function(a){return b.updateMethod=a,this},this.httpConfig=function(a){return b.httpConfig=a,this},this.defaultParams=function(a){return b.defaultParams=a,this},this.$get=["$http","$q","railsUrlBuilder","railsSerializer","railsRootWrappingTransformer","railsRootWrappingInterceptor","RailsResourceInjector",function(c,d,e,f,g,h,i){function j(a,b){return b&&("/"!==b[0]&&(a+="/"),a+=b),a}function k(a,b){for(var c,d=0,e=a.length;e>d;d++)c=a[d],angular.isString(c)&&(c=a[d]=i.getDependency(c)),b(c)}function l(a){var b=this;if(a){var c=function(a){return{resource:l,context:b,response:a,then:function(a){return this.response=a(this.response,this.resource,this.context),c(this.response)}}},d=this.constructor.callInterceptors(c({data:a}),this).response.data;angular.extend(this,d)}}return l.extend=function(a){function b(){this.constructor=a}var c={}.hasOwnProperty,d=this;for(var e in d)c.call(d,e)&&(a[e]=d[e]);return b.prototype=d.prototype,a.prototype=new b,a.__super__=d.prototype,a},l.configure=function(c){c=c||{},this.config&&(c=angular.extend({},this.config,c)),this.config={},this.config.url=c.url,this.config.rootWrapping=c.rootWrapping===a?b.rootWrapping:c.rootWrapping,this.config.httpConfig=c.httpConfig||b.httpConfig,this.config.httpConfig.headers=angular.extend({Accept:"application/json","Content-Type":"application/json"},this.config.httpConfig.headers||{}),this.config.defaultParams=c.defaultParams||b.defaultParams,this.config.updateMethod=(c.updateMethod||b.updateMethod).toLowerCase(),this.config.requestTransformers=c.requestTransformers?c.requestTransformers.slice(0):[],this.config.responseInterceptors=c.responseInterceptors?c.responseInterceptors.slice(0):[],this.config.afterResponseInterceptors=c.afterResponseInterceptors?c.afterResponseInterceptors.slice(0):[],this.config.serializer=angular.isObject(c.serializer)?c.serializer:i.createService(c.serializer||f()),this.config.name=this.config.serializer.underscore(c.name),this.config.pluralName=this.config.serializer.underscore(c.pluralName||this.config.serializer.pluralize(this.config.name)),this.config.urlBuilder=e(this.config.url),this.config.resourceConstructor=this},l.configure({}),l.setUrl=function(a){this.configure({url:a})},l.buildUrl=function(a){return this.config.urlBuilder(a)},l.beforeResponse=function(a){a=i.getDependency(a),this.config.responseInterceptors.push(function(b){return b.then(function(c){return a(c.data,b.resource.config.resourceConstructor,b.context),c})})},l.afterResponse=function(a){a=i.getDependency(a),this.config.afterResponseInterceptors.push(function(b){return b.then(function(c){return a(c,b.resource.config.resourceConstructor),c})})},l.beforeRequest=function(a){a=i.getDependency(a),this.config.requestTransformers.push(function(b,c){return a(b,c.config.resourceConstructor)||b})},l.transformData=function(a){var b=this.config;return a=b.serializer.serialize(a),k(this.config.requestTransformers,function(c){a=c(a,b.resourceConstructor)}),b.rootWrapping&&(a=g(a,b.resourceConstructor)),a},l.callInterceptors=function(a,b){var c=this.config;return a=a.then(function(a){return a.originalData=a.data,a}),c.rootWrapping&&(a.resource=c.resourceConstructor,a=h(a)),a.then(function(a){return a.data=c.serializer.deserialize(a.data,c.resourceConstructor),a}),k(c.responseInterceptors,function(d){a.resource=c.resourceConstructor,a.context=b,a=d(a)}),a},l.callAfterInterceptors=function(a){var b=this.config;return k(b.afterResponseInterceptors,function(c){a.resource=b.resourceConstructor,a=c(a)}),a},l.processResponse=function(a){return a=this.callInterceptors(a).then(function(a){return a.data}),this.callAfterInterceptors(a)},l.getParameters=function(a){var b;return this.config.defaultParams&&(b=this.config.defaultParams),angular.isObject(a)&&(b=angular.extend(b||{},a)),b},l.getHttpConfig=function(a){var b=this.getParameters(a);return b?angular.extend({params:b},this.config.httpConfig):angular.copy(this.config.httpConfig)},l.$url=l.resourceUrl=function(a,b){return angular.isObject(a)||(a={id:a}),j(this.buildUrl(a||{}),b)},l.$get=function(a,b){return this.processResponse(c.get(a,this.getHttpConfig(b)))},l.query=function(a,b){return this.$get(this.resourceUrl(b),a)},l.get=function(a,b){return this.$get(this.resourceUrl(a),b)},l.prototype.$url=function(a){return j(this.constructor.resourceUrl(this),a)},l.prototype.processResponse=function(a){return a=this.constructor.callInterceptors(a,this),a=a.then(angular.bind(this,function(a){return a.hasOwnProperty("data")&&angular.isObject(a.data)&&angular.extend(this,a.data),this})),this.constructor.callAfterInterceptors(a)},angular.forEach(["post","put","patch"],function(a){l["$"+a]=function(b,d){var e;return d=this.transformData(angular.copy(d,{})),e=angular.extend({method:a,url:b,data:d},this.getHttpConfig()),this.processResponse(c(e))},l.prototype["$"+a]=function(b){var d,e;return d=this.constructor.transformData(angular.copy(this,{})),e=angular.extend({method:a,url:b,data:d},this.constructor.getHttpConfig()),this.processResponse(c(e))}}),l.prototype.create=function(){return this.$post(this.$url(),this)},l.prototype.update=function(){return this["$"+this.constructor.config.updateMethod](this.$url(),this)},l.prototype.isNew=function(){return null==this.id},l.prototype.save=function(){return this.isNew()?this.create():this.update()},l.$delete=function(a){return this.processResponse(c["delete"](a,this.getHttpConfig()))},l.prototype.$delete=function(a){return this.processResponse(c["delete"](a,this.constructor.getHttpConfig()))},l.prototype.remove=l.prototype["delete"]=function(){return this.$delete(this.$url())},l}]}),angular.module("rails").factory("railsResourceFactory",["RailsResource",function(a){return function(b){function c(){c.__super__.constructor.apply(this,arguments)}return a.extend(c),c.configure(b),c}}])}();
Binary file
data/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "angularjs-rails-resource",
3
- "version": "0.2.5",
3
+ "version": "1.0.0-pre1",
4
4
  "main": "angularjs-rails-resource.js",
5
5
  "description": "A resource factory inspired by $resource from AngularJS",
6
6
  "repository": {
@@ -1,7 +1,7 @@
1
1
  module Angularjs
2
2
  module Rails
3
3
  module Resource
4
- VERSION = '0.2.5'
4
+ VERSION = '1.0.0.pre.1'
5
5
  end
6
6
  end
7
7
  end
data/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "angularjs-rails-resource",
3
- "description": "A resource factory inspired by $resource from AngularJS",
4
- "version": "0.2.5",
5
- "main": "dist/angularjs-rails-resource.min.js",
6
- "homepage": "https://github.com/FineLinePrototyping/angularjs-rails-resource.git",
7
- "author": "",
3
+ "description" : "A resource factory inspired by $resource from AngularJS",
4
+ "version": "1.0.0-pre1",
5
+ "main" : "dist/angularjs-rails-resource.min.js",
6
+ "homepage" : "https://github.com/FineLinePrototyping/angularjs-rails-resource.git",
7
+ "author" : "",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/FineLinePrototyping/angularjs-rails-resource.git"
@@ -2,42 +2,42 @@ describe('resource provider factory config', function () {
2
2
  'use strict';
3
3
 
4
4
  it('should allow disabling root wrapping globally', function () {
5
- module('rails', function (railsResourceFactoryProvider) {
6
- expect(railsResourceFactoryProvider.enableRootWrapping(false)).toBe(railsResourceFactoryProvider);
5
+ module('rails', function (RailsResourceProvider) {
6
+ expect(RailsResourceProvider.rootWrapping(false)).toBe(RailsResourceProvider);
7
7
  });
8
8
 
9
9
  inject(function (railsResourceFactory) {
10
- expect(railsResourceFactory({name: 'test', url: '/test'}).enableRootWrapping).toBe(false);
10
+ expect(railsResourceFactory({name: 'test', url: '/test'}).config.rootWrapping).toBe(false);
11
11
  });
12
12
  });
13
13
 
14
14
  it('should allow setting updateMethod globally', function () {
15
- module('rails', function (railsResourceFactoryProvider) {
16
- expect(railsResourceFactoryProvider.updateMethod('patch')).toBe(railsResourceFactoryProvider);
15
+ module('rails', function (RailsResourceProvider) {
16
+ expect(RailsResourceProvider.updateMethod('patch')).toBe(RailsResourceProvider);
17
17
  });
18
18
 
19
19
  inject(function (railsResourceFactory) {
20
- expect(railsResourceFactory({name: 'test', url: '/test'}).updateMethod).toBe('patch');
20
+ expect(railsResourceFactory({name: 'test', url: '/test'}).config.updateMethod).toBe('patch');
21
21
  });
22
22
  });
23
23
 
24
24
  it('should allow setting http headers options globally', function () {
25
- module('rails', function (railsResourceFactoryProvider) {
26
- expect(railsResourceFactoryProvider.httpConfig({headers: {'test': "header"}})).toBe(railsResourceFactoryProvider);
25
+ module('rails', function (RailsResourceProvider) {
26
+ expect(RailsResourceProvider.httpConfig({headers: {'test': "header"}})).toBe(RailsResourceProvider);
27
27
  });
28
28
 
29
29
  inject(function (railsResourceFactory) {
30
- expect(railsResourceFactory({name: 'test', url: '/test'}).httpConfig.headers).toEqualData({'Accept': 'application/json', 'Content-Type': 'application/json', 'test': 'header'});
30
+ expect(railsResourceFactory({name: 'test', url: '/test'}).config.httpConfig.headers).toEqualData({'Accept': 'application/json', 'Content-Type': 'application/json', 'test': 'header'});
31
31
  });
32
32
  });
33
33
 
34
34
  it('should allow setting default query parameters options globally', function () {
35
- module('rails', function (railsResourceFactoryProvider) {
36
- expect(railsResourceFactoryProvider.defaultParams({'test': "1"})).toBe(railsResourceFactoryProvider);
35
+ module('rails', function (RailsResourceProvider) {
36
+ expect(RailsResourceProvider.defaultParams({'test': "1"})).toBe(RailsResourceProvider);
37
37
  });
38
38
 
39
39
  inject(function (railsResourceFactory) {
40
- expect(railsResourceFactory({name: 'test', url: '/test'}).defaultParams).toEqualData({'test': '1'});
40
+ expect(railsResourceFactory({name: 'test', url: '/test'}).config.defaultParams).toEqualData({'test': '1'});
41
41
  });
42
42
  });
43
43
  });
@@ -85,7 +85,7 @@ describe('railsResourceFactory', function () {
85
85
  url: '/authors',
86
86
  name: 'author',
87
87
  serializer: railsSerializer(function () {
88
- this.resource('books', Book)
88
+ this.resource('books', Book);
89
89
  this.exclude('birthDate');
90
90
  })
91
91
  });
@@ -381,6 +381,17 @@ describe('railsResourceFactory', function () {
381
381
  expect(test).toEqualData({id: 123, abcDef: "T"});
382
382
  });
383
383
 
384
+ it('should allow changing urls after first operation', function () {
385
+ $httpBackend.expectGET('/test/123').respond(200, {test: {id: 123, abc: 'xyz'}});
386
+ Test.get(123);
387
+ $httpBackend.flush();
388
+
389
+ $httpBackend.expectGET('/test2/123').respond(200, {test: {id: 123, abc: 'xyz'}});
390
+ Test.setUrl('/test2');
391
+ Test.get(123);
392
+ $httpBackend.flush();
393
+ });
394
+
384
395
  it('should support constructing with date properties', function () {
385
396
  var testDate = new Date(),
386
397
  test = new Test({id: 123, testDate: testDate});
@@ -415,14 +426,6 @@ describe('railsResourceFactory', function () {
415
426
  expect(test).toEqualData({id: 123, abc: 'xyz', xyz: 'abc', extra: 'test'});
416
427
  }));
417
428
  });
418
-
419
- it('should be able to $post an array of resources', function () {
420
- var data = [{id: 123, abc: 'xyz'}, {id: 124, abc: 'xyz'}];
421
- $httpBackend['expectPOST']('/xyz', {tests: data} ).respond(200, {tests: data});
422
- Test.$post('/xyz', data);
423
- $httpBackend.flush();
424
- });
425
-
426
429
  });
427
430
 
428
431
  describe('plural', function() {
@@ -484,4 +487,92 @@ describe('railsResourceFactory', function () {
484
487
  expect(result.length).toBe(0);
485
488
  }));
486
489
  });
490
+
491
+ describe('subclassing', function() {
492
+ var $httpBackend, $rootScope, Book, CarManual,
493
+ // generated CoffeeScript Code
494
+ __hasProp = {}.hasOwnProperty,
495
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
496
+
497
+
498
+ beforeEach(inject(function (_$httpBackend_, _$rootScope_, RailsResource) {
499
+ $httpBackend = _$httpBackend_;
500
+ $rootScope = _$rootScope_;
501
+
502
+ // generated CoffeeScript Code
503
+ Book = (function(_super) {
504
+ __extends(Book, _super);
505
+
506
+ // @configure url: '/books', name: 'book'
507
+ Book.configure({ url: '/books', name: 'book' });
508
+
509
+ function Book() {
510
+ Book.__super__.constructor.apply(this, arguments);
511
+ this.subclass = true;
512
+ }
513
+
514
+ return Book;
515
+
516
+ })(RailsResource);
517
+
518
+ CarManual = (function(_super) {
519
+ __extends(CarManual, _super);
520
+
521
+ CarManual.configure({ url: '/car_manuals', name: 'car_manual' });
522
+
523
+ function CarManual() {
524
+ CarManual.__super__.constructor.apply(this, arguments);
525
+ this.subclass = true;
526
+ }
527
+
528
+ return CarManual;
529
+
530
+ })(Book);
531
+ }));
532
+
533
+ afterEach(function() {
534
+ $httpBackend.verifyNoOutstandingExpectation();
535
+ $httpBackend.verifyNoOutstandingRequest();
536
+ });
537
+
538
+ it('get should return resource instance of subclass', function() {
539
+ var promise, result;
540
+
541
+ $httpBackend.expectGET('/car_manuals/123').respond(200, {car_manual: {id: 123, abc: 'xyz'}});
542
+
543
+ expect(promise = CarManual.get(123)).toBeDefined();
544
+
545
+ promise.then(function (response) {
546
+ result = response;
547
+ });
548
+
549
+ $httpBackend.flush();
550
+
551
+ expect(result).toBeInstanceOf(CarManual);
552
+ expect(result).toEqualData({id: 123, abc: 'xyz', subclass: true});
553
+ });
554
+
555
+ it('should have configuration per-class', function() {
556
+ var promise, result;
557
+
558
+ $httpBackend.expectGET('/books/123').respond(200, {book: {id: 123, abc: 'xyz'}});
559
+
560
+ expect(promise = Book.get(123)).toBeDefined();
561
+
562
+ promise.then(function (response) {
563
+ result = response;
564
+ });
565
+
566
+ $httpBackend.flush();
567
+
568
+ expect(result).toBeInstanceOf(Book);
569
+ expect(result).toEqualData({id: 123, abc: 'xyz', subclass: true});
570
+ });
571
+
572
+ it('should allow constructing subclasses with data', function () {
573
+ var carManual = new CarManual({id: 1, name: 'Honda CR-V'});
574
+ expect(carManual.id).toBe(1);
575
+ expect(carManual.name).toBe('Honda CR-V');
576
+ });
577
+ });
487
578
  });
@@ -5,7 +5,7 @@ describe('root wrapping', function () {
5
5
 
6
6
  var q, rootScope,
7
7
  transformer, interceptor,
8
- config = {rootName: 'test', rootPluralName: 'tests'};
8
+ config = {config: {name: 'test', pluralName: 'tests'}};
9
9
 
10
10
 
11
11
  function testTransform(wrappedData, unwrappedData) {
@@ -390,22 +390,6 @@ describe('railsSerializer', function () {
390
390
  result = serializer.deserialize({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
391
391
  expect(result).toEqualData({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
392
392
  });
393
-
394
- it('should only serialize id and books', function() {
395
- var result,
396
- serializer = createSerializer(function(config) {
397
- this.only('id', 'books');
398
- this.nestedAttribute('books');
399
- this.serializeWith('books', factory(function() { }));
400
- });
401
- var book = { id: 1, title: 'A Game of Thrones', publicationDate: '1996-08-06' };
402
- result = serializer.serialize({
403
- id: 1, first: 'George', last: 'Martin', books: [book]
404
- });
405
- expect(result).toEqualData({ id: 1, books_attributes: [{ id: 1, title: 'A Game of Thrones', publication_date: '1996-08-06' }] });
406
- result = serializer.deserialize(result);
407
- expect(result).toEqual({ id: 1, books: [book]});
408
- });
409
393
  });
410
394
  });
411
395
  });
@@ -2,7 +2,7 @@
2
2
  angular.module('rails').factory('railsRootWrappingTransformer', function () {
3
3
  return function (data, resource) {
4
4
  var result = {};
5
- result[angular.isArray(data) ? resource.rootPluralName : resource.rootName] = data;
5
+ result[angular.isArray(data) ? resource.config.pluralName : resource.config.name] = data;
6
6
  return result;
7
7
  };
8
8
  });
@@ -16,10 +16,10 @@
16
16
  }
17
17
 
18
18
  return promise.then(function (response) {
19
- if (response.data && response.data.hasOwnProperty(resource.rootName)) {
20
- response.data = response.data[resource.rootName];
21
- } else if (response.data && response.data.hasOwnProperty(resource.rootPluralName)) {
22
- response.data = response.data[resource.rootPluralName];
19
+ if (response.data && response.data.hasOwnProperty(resource.config.name)) {
20
+ response.data = response.data[resource.config.name];
21
+ } else if (response.data && response.data.hasOwnProperty(resource.config.pluralName)) {
22
+ response.data = response.data[resource.config.pluralName];
23
23
  }
24
24
 
25
25
  return response;
@@ -27,16 +27,16 @@
27
27
  };
28
28
  });
29
29
 
30
- angular.module('rails').provider('railsResourceFactory', function () {
30
+ angular.module('rails').provider('RailsResource', function () {
31
31
  var defaultOptions = {
32
- enableRootWrapping: true,
32
+ rootWrapping: true,
33
33
  updateMethod: 'put',
34
34
  httpConfig: {},
35
35
  defaultParams: undefined
36
36
  };
37
37
 
38
- this.enableRootWrapping = function (value) {
39
- defaultOptions.enableRootWrapping = value;
38
+ this.rootWrapping = function (value) {
39
+ defaultOptions.rootWrapping = value;
40
40
  return this;
41
41
  };
42
42
 
@@ -58,11 +58,6 @@
58
58
  this.$get = ['$http', '$q', 'railsUrlBuilder', 'railsSerializer', 'railsRootWrappingTransformer', 'railsRootWrappingInterceptor', 'RailsResourceInjector',
59
59
  function ($http, $q, railsUrlBuilder, railsSerializer, railsRootWrappingTransformer, railsRootWrappingInterceptor, RailsResourceInjector) {
60
60
 
61
- function railsResourceFactory(config) {
62
- var transformers = config.requestTransformers,
63
- interceptors = config.responseInterceptors,
64
- afterInterceptors = config.afterResponseInterceptors;
65
-
66
61
  function appendPath(url, path) {
67
62
  if (path) {
68
63
  if (path[0] !== '/') {
@@ -75,43 +70,100 @@
75
70
  return url;
76
71
  }
77
72
 
73
+ function forEachDependency(list, callback) {
74
+ var dependency;
75
+
76
+ for (var i = 0, len = list.length; i < len; i++) {
77
+ dependency = list[i];
78
+
79
+ if (angular.isString(dependency)) {
80
+ dependency = list[i] = RailsResourceInjector.getDependency(dependency);
81
+ }
82
+
83
+ callback(dependency);
84
+ }
85
+ }
86
+
78
87
  function RailsResource(value) {
79
88
  var instance = this;
80
89
  if (value) {
81
- var immediatePromise = function(data) {
90
+ var immediatePromise = function (data) {
82
91
  return {
83
92
  resource: RailsResource,
84
93
  context: instance,
85
94
  response: data,
86
- then: function(callback) {
95
+ then: function (callback) {
87
96
  this.response = callback(this.response, this.resource, this.context);
88
97
  return immediatePromise(this.response);
89
98
  }
90
99
  }
91
100
  };
92
101
 
93
- var data = RailsResource.callInterceptors(immediatePromise({data: value}), this).response.data;
102
+ var data = this.constructor.callInterceptors(immediatePromise({data: value}), this).response.data;
94
103
  angular.extend(this, data);
95
104
  }
96
105
  }
97
106
 
98
- RailsResource.setUrl = function(url) {
99
- RailsResource.url = railsUrlBuilder(url);
107
+ RailsResource.extend = function (child) {
108
+ // Extend logic copied from CoffeeScript generated code
109
+ var __hasProp = {}.hasOwnProperty, parent = this;
110
+ for (var key in parent) {
111
+ if (__hasProp.call(parent, key)) child[key] = parent[key];
112
+ }
113
+
114
+ function ctor() {
115
+ this.constructor = child;
116
+ }
117
+
118
+ ctor.prototype = parent.prototype;
119
+ child.prototype = new ctor();
120
+ child.__super__ = parent.prototype;
121
+ return child;
100
122
  };
101
- RailsResource.setUrl(config.url);
102
123
 
103
- RailsResource.enableRootWrapping = config.wrapData === undefined ? defaultOptions.enableRootWrapping : config.wrapData; // using undefined check because config.wrapData || true would be true when config.wrapData === false
104
- RailsResource.httpConfig = config.httpConfig || defaultOptions.httpConfig;
105
- RailsResource.httpConfig.headers = angular.extend({'Accept': 'application/json', 'Content-Type': 'application/json'}, RailsResource.httpConfig.headers || {});
106
- RailsResource.defaultParams = config.defaultParams || defaultOptions.defaultParams;
107
- RailsResource.updateMethod = (config.updateMethod || defaultOptions.updateMethod).toLowerCase();
124
+ // allow calling configure multiple times to set configuration options and override values from inherited resources
125
+ RailsResource.configure = function (cfg) {
126
+ cfg = cfg || {};
127
+
128
+ if (this.config) {
129
+ cfg = angular.extend({}, this.config, cfg);
130
+ }
131
+
132
+ this.config = {};
133
+ this.config.url = cfg.url;
134
+ this.config.rootWrapping = cfg.rootWrapping === undefined ? defaultOptions.rootWrapping : cfg.rootWrapping; // using undefined check because config.rootWrapping || true would be true when config.rootWrapping === false
135
+ this.config.httpConfig = cfg.httpConfig || defaultOptions.httpConfig;
136
+ this.config.httpConfig.headers = angular.extend({'Accept': 'application/json', 'Content-Type': 'application/json'}, this.config.httpConfig.headers || {});
137
+ this.config.defaultParams = cfg.defaultParams || defaultOptions.defaultParams;
138
+ this.config.updateMethod = (cfg.updateMethod || defaultOptions.updateMethod).toLowerCase();
139
+
140
+ this.config.requestTransformers = cfg.requestTransformers ? cfg.requestTransformers.slice(0) : [];
141
+ this.config.responseInterceptors = cfg.responseInterceptors ? cfg.responseInterceptors.slice(0) : [];
142
+ this.config.afterResponseInterceptors = cfg.afterResponseInterceptors ? cfg.afterResponseInterceptors.slice(0) : [];
143
+
144
+ // strings and functions are not considered objects by angular.isObject()
145
+ if (angular.isObject(cfg.serializer)) {
146
+ this.config.serializer = cfg.serializer;
147
+ } else {
148
+ this.config.serializer = RailsResourceInjector.createService(cfg.serializer || railsSerializer());
149
+ }
150
+
151
+ this.config.name = this.config.serializer.underscore(cfg.name);
152
+ this.config.pluralName = this.config.serializer.underscore(cfg.pluralName || this.config.serializer.pluralize(this.config.name));
108
153
 
109
- RailsResource.requestTransformers = [];
110
- RailsResource.responseInterceptors = [];
111
- RailsResource.afterResponseInterceptors = [];
112
- RailsResource.serializer = RailsResourceInjector.createService(config.serializer || railsSerializer());
113
- RailsResource.rootName = RailsResource.serializer.underscore(config.name);
114
- RailsResource.rootPluralName = RailsResource.serializer.underscore(config.pluralName || RailsResource.serializer.pluralize(config.name));
154
+ this.config.urlBuilder = railsUrlBuilder(this.config.url);
155
+ this.config.resourceConstructor = this;
156
+ };
157
+
158
+ RailsResource.configure({});
159
+
160
+ RailsResource.setUrl = function (url) {
161
+ this.configure({url: url});
162
+ };
163
+
164
+ RailsResource.buildUrl = function (context) {
165
+ return this.config.urlBuilder(context);
166
+ };
115
167
 
116
168
  /**
117
169
  * Add a callback to run on response and construction.
@@ -119,11 +171,11 @@
119
171
  * constructor is the resource class calling the function,
120
172
  * context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
121
173
  */
122
- RailsResource.beforeResponse = function(fn) {
174
+ RailsResource.beforeResponse = function (fn) {
123
175
  fn = RailsResourceInjector.getDependency(fn);
124
- RailsResource.responseInterceptors.push(function(promise) {
125
- return promise.then(function(response) {
126
- fn(response.data, promise.resource, promise.context);
176
+ this.config.responseInterceptors.push(function (promise) {
177
+ return promise.then(function (response) {
178
+ fn(response.data, promise.resource.config.resourceConstructor, promise.context);
127
179
  return response;
128
180
  });
129
181
  });
@@ -133,11 +185,11 @@
133
185
  * Add a callback to run after response has been processed. These callbacks are not called on object construction.
134
186
  * @param fn(response data, constructor) - response data is either the resource instance returned or an array of resource instances and constructor is the resource class calling the function
135
187
  */
136
- RailsResource.afterResponse = function(fn) {
188
+ RailsResource.afterResponse = function (fn) {
137
189
  fn = RailsResourceInjector.getDependency(fn);
138
- RailsResource.afterResponseInterceptors.push(function(promise) {
139
- return promise.then(function(response) {
140
- fn(response, promise.resource);
190
+ this.config.afterResponseInterceptors.push(function (promise) {
191
+ return promise.then(function (response) {
192
+ fn(response, promise.resource.config.resourceConstructor);
141
193
  return response;
142
194
  });
143
195
  });
@@ -147,38 +199,24 @@
147
199
  * Adds a function to run after serializing the data to send to the server, but before root-wrapping it.
148
200
  * @param fn (data, constructor) - data object is the serialized resource instance, and constructor the resource class calling the function
149
201
  */
150
- RailsResource.beforeRequest = function(fn) {
202
+ RailsResource.beforeRequest = function (fn) {
151
203
  fn = RailsResourceInjector.getDependency(fn);
152
- RailsResource.requestTransformers.push(function(data, resource) {
153
- return fn(data, resource) || data;
204
+ this.config.requestTransformers.push(function (data, resource) {
205
+ return fn(data, resource.config.resourceConstructor) || data;
154
206
  });
155
207
  };
156
208
 
157
- // copied from $HttpProvider to support interceptors being dependency names or anonymous factory functions
158
- angular.forEach(interceptors, function (interceptor) {
159
- RailsResource.responseInterceptors.push(RailsResourceInjector.getDependency(interceptor));
160
- });
161
-
162
- angular.forEach(afterInterceptors, function (interceptor) {
163
- RailsResource.afterResponseInterceptors.push(RailsResourceInjector.getDependency(interceptor));
164
- });
165
-
166
- angular.forEach(transformers, function (transformer) {
167
- RailsResource.requestTransformers.push(RailsResourceInjector.getDependency(transformer));
168
- });
169
-
170
209
  // transform data for request:
171
210
  RailsResource.transformData = function (data) {
172
- data = RailsResource.serializer.serialize(data);
211
+ var config = this.config;
212
+ data = config.serializer.serialize(data);
173
213
 
174
- // data is now serialized. call request transformers including beforeRequest
175
- angular.forEach(RailsResource.requestTransformers, function (transformer) {
176
- data = transformer(data, RailsResource);
214
+ forEachDependency(this.config.requestTransformers, function (transformer) {
215
+ data = transformer(data, config.resourceConstructor);
177
216
  });
178
217
 
179
-
180
- if (RailsResource.enableRootWrapping) {
181
- data = railsRootWrappingTransformer(data, RailsResource);
218
+ if (config.rootWrapping) {
219
+ data = railsRootWrappingTransformer(data, config.resourceConstructor);
182
220
  }
183
221
 
184
222
  return data;
@@ -186,25 +224,27 @@
186
224
 
187
225
  // transform data on response:
188
226
  RailsResource.callInterceptors = function (promise, context) {
227
+ var config = this.config;
228
+
189
229
  promise = promise.then(function (response) {
190
230
  // store off the data in case something (like our root unwrapping) assigns data as a new object
191
231
  response.originalData = response.data;
192
232
  return response;
193
233
  });
194
234
 
195
- if (RailsResource.enableRootWrapping) {
196
- promise.resource = RailsResource;
235
+ if (config.rootWrapping) {
236
+ promise.resource = config.resourceConstructor;
197
237
  promise = railsRootWrappingInterceptor(promise);
198
238
  }
199
239
 
200
240
  promise.then(function (response) {
201
- response.data = RailsResource.serializer.deserialize(response.data, RailsResource);
241
+ response.data = config.serializer.deserialize(response.data, config.resourceConstructor);
202
242
  return response;
203
243
  });
204
244
 
205
245
  // data is now deserialized. call response interceptors including beforeResponse
206
- angular.forEach(RailsResource.responseInterceptors, function (interceptor) {
207
- promise.resource = RailsResource;
246
+ forEachDependency(config.responseInterceptors, function (interceptor) {
247
+ promise.resource = config.resourceConstructor;
208
248
  promise.context = context;
209
249
  promise = interceptor(promise);
210
250
  });
@@ -214,9 +254,10 @@
214
254
 
215
255
  // transform data after response has been converted to a resource instance:
216
256
  RailsResource.callAfterInterceptors = function (promise) {
257
+ var config = this.config;
217
258
  // data is now deserialized. call response interceptors including afterResponse
218
- angular.forEach(RailsResource.afterResponseInterceptors, function (interceptor) {
219
- promise.resource = RailsResource;
259
+ forEachDependency(config.afterResponseInterceptors, function (interceptor) {
260
+ promise.resource = config.resourceConstructor;
220
261
  promise = interceptor(promise);
221
262
  });
222
263
 
@@ -224,18 +265,18 @@
224
265
  };
225
266
 
226
267
  RailsResource.processResponse = function (promise) {
227
- promise = RailsResource.callInterceptors(promise).then(function (response) {
268
+ promise = this.callInterceptors(promise).then(function (response) {
228
269
  return response.data;
229
270
  });
230
271
 
231
- return RailsResource.callAfterInterceptors(promise);
272
+ return this.callAfterInterceptors(promise);
232
273
  };
233
274
 
234
275
  RailsResource.getParameters = function (queryParams) {
235
276
  var params;
236
277
 
237
- if (RailsResource.defaultParams) {
238
- params = RailsResource.defaultParams;
278
+ if (this.config.defaultParams) {
279
+ params = this.config.defaultParams;
239
280
  }
240
281
 
241
282
  if (angular.isObject(queryParams)) {
@@ -246,13 +287,13 @@
246
287
  };
247
288
 
248
289
  RailsResource.getHttpConfig = function (queryParams) {
249
- var params = RailsResource.getParameters(queryParams);
290
+ var params = this.getParameters(queryParams);
250
291
 
251
292
  if (params) {
252
- return angular.extend({params: params}, RailsResource.httpConfig);
293
+ return angular.extend({params: params}, this.config.httpConfig);
253
294
  }
254
295
 
255
- return angular.copy(RailsResource.httpConfig);
296
+ return angular.copy(this.config.httpConfig);
256
297
  };
257
298
 
258
299
  /**
@@ -275,19 +316,19 @@
275
316
  context = {id: context};
276
317
  }
277
318
 
278
- return appendPath(RailsResource.url(context || {}), path);
319
+ return appendPath(this.buildUrl(context || {}), path);
279
320
  };
280
321
 
281
322
  RailsResource.$get = function (url, queryParams) {
282
- return RailsResource.processResponse($http.get(url, RailsResource.getHttpConfig(queryParams)));
323
+ return this.processResponse($http.get(url, this.getHttpConfig(queryParams)));
283
324
  };
284
325
 
285
326
  RailsResource.query = function (queryParams, context) {
286
- return RailsResource.$get(RailsResource.resourceUrl(context), queryParams);
327
+ return this.$get(this.resourceUrl(context), queryParams);
287
328
  };
288
329
 
289
330
  RailsResource.get = function (context, queryParams) {
290
- return RailsResource.$get(RailsResource.resourceUrl(context), queryParams);
331
+ return this.$get(this.resourceUrl(context), queryParams);
291
332
  };
292
333
 
293
334
  /**
@@ -296,12 +337,12 @@
296
337
  * @param path {string} (optional) An additional path to append to the URL
297
338
  * @returns {string} The URL for the resource
298
339
  */
299
- RailsResource.prototype.$url = function(path) {
300
- return appendPath(RailsResource.resourceUrl(this), path);
340
+ RailsResource.prototype.$url = function (path) {
341
+ return appendPath(this.constructor.resourceUrl(this), path);
301
342
  };
302
343
 
303
344
  RailsResource.prototype.processResponse = function (promise) {
304
- promise = RailsResource.callInterceptors(promise, this);
345
+ promise = this.constructor.callInterceptors(promise, this);
305
346
 
306
347
  promise = promise.then(angular.bind(this, function (response) {
307
348
  // we may not have response data
@@ -312,23 +353,23 @@
312
353
  return this;
313
354
  }));
314
355
 
315
- return RailsResource.callAfterInterceptors(promise);
356
+ return this.constructor.callAfterInterceptors(promise);
316
357
  };
317
358
 
318
359
  angular.forEach(['post', 'put', 'patch'], function (method) {
319
360
  RailsResource['$' + method] = function (url, data) {
320
361
  var config;
321
362
  // clone so we can manipulate w/o modifying the actual instance
322
- data = RailsResource.transformData(angular.copy(data));
323
- config = angular.extend({method: method, url: url, data: data}, RailsResource.getHttpConfig());
324
- return RailsResource.processResponse($http(config));
363
+ data = this.transformData(angular.copy(data, {}));
364
+ config = angular.extend({method: method, url: url, data: data}, this.getHttpConfig());
365
+ return this.processResponse($http(config));
325
366
  };
326
367
 
327
368
  RailsResource.prototype['$' + method] = function (url) {
328
369
  var data, config;
329
370
  // clone so we can manipulate w/o modifying the actual instance
330
- data = RailsResource.transformData(angular.copy(this, {}));
331
- config = angular.extend({method: method, url: url, data: data}, RailsResource.getHttpConfig());
371
+ data = this.constructor.transformData(angular.copy(this, {}));
372
+ config = angular.extend({method: method, url: url, data: data}, this.constructor.getHttpConfig());
332
373
  return this.processResponse($http(config));
333
374
 
334
375
  };
@@ -339,12 +380,12 @@
339
380
  };
340
381
 
341
382
  RailsResource.prototype.update = function () {
342
- return this['$' + RailsResource.updateMethod](this.$url(), this);
383
+ return this['$' + this.constructor.config.updateMethod](this.$url(), this);
343
384
  };
344
385
 
345
386
  RailsResource.prototype.isNew = function () {
346
387
  return this.id == null;
347
- }
388
+ };
348
389
 
349
390
  RailsResource.prototype.save = function () {
350
391
  if (this.isNew()) {
@@ -352,14 +393,14 @@
352
393
  } else {
353
394
  return this.update();
354
395
  }
355
- }
396
+ };
356
397
 
357
398
  RailsResource['$delete'] = function (url) {
358
- return RailsResource.processResponse($http['delete'](url, RailsResource.getHttpConfig()));
399
+ return this.processResponse($http['delete'](url, this.getHttpConfig()));
359
400
  };
360
401
 
361
402
  RailsResource.prototype['$delete'] = function (url) {
362
- return this.processResponse($http['delete'](url, RailsResource.getHttpConfig()));
403
+ return this.processResponse($http['delete'](url, this.constructor.getHttpConfig()));
363
404
  };
364
405
 
365
406
  //using ['delete'] instead of .delete for IE7/8 compatibility
@@ -368,9 +409,20 @@
368
409
  };
369
410
 
370
411
  return RailsResource;
412
+ }];
413
+ });
414
+
415
+ angular.module('rails').factory('railsResourceFactory', ['RailsResource', function (RailsResource) {
416
+ return function (config) {
417
+ function Resource() {
418
+ Resource.__super__.constructor.apply(this, arguments);
371
419
  }
372
420
 
373
- return railsResourceFactory;
374
- }];
375
- });
421
+ RailsResource.extend(Resource);
422
+ Resource.configure(config);
423
+
424
+ return Resource;
425
+ }
426
+ }]);
427
+
376
428
  }());