From a31573e9fbf345523ea81b85c3048e79673788ed Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Tue, 3 Sep 2013 18:23:09 +0530 Subject: [PATCH 01/18] Fixing a documentation bug --- README.mkd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.mkd b/README.mkd index ccdcc35..45cd784 100644 --- a/README.mkd +++ b/README.mkd @@ -76,7 +76,7 @@ var email = BackboneFactory.next('email') // person1@example.com var userFactory = BackboneFactory.define('user', User, function(){ return { name : 'Backbone User', - email: BackboneFactory.next('person_email') + email: BackboneFactory.next('email') }; } ); From 2ec718fbb4b473274fac871d11b8d93b7319d1fa Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Tue, 3 Sep 2013 20:40:14 +0530 Subject: [PATCH 02/18] Upgrading underscore.js to latest (1.5.1) --- public/javascripts/underscore-min.js | 32 ++++++---------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/public/javascripts/underscore-min.js b/public/javascripts/underscore-min.js index f502cf9..ef9ef9f 100644 --- a/public/javascripts/underscore-min.js +++ b/public/javascripts/underscore-min.js @@ -1,26 +1,6 @@ -// Underscore.js 1.1.6 -// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore is freely distributable under the MIT license. -// Portions of Underscore are inspired or borrowed from Prototype, -// Oliver Steele's Functional, and John Resig's Micro-Templating. -// For all details and documentation: -// http://documentcloud.github.com/underscore -(function(){var p=this,C=p._,m={},i=Array.prototype,n=Object.prototype,f=i.slice,D=i.unshift,E=n.toString,l=n.hasOwnProperty,s=i.forEach,t=i.map,u=i.reduce,v=i.reduceRight,w=i.filter,x=i.every,y=i.some,o=i.indexOf,z=i.lastIndexOf;n=Array.isArray;var F=Object.keys,q=Function.prototype.bind,b=function(a){return new j(a)};typeof module!=="undefined"&&module.exports?(module.exports=b,b._=b):p._=b;b.VERSION="1.1.6";var h=b.each=b.forEach=function(a,c,d){if(a!=null)if(s&&a.forEach===s)a.forEach(c,d);else if(b.isNumber(a.length))for(var e= -0,k=a.length;e=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a, -c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};h(a,function(a,b,f){b=c?c.call(d,a,b,f):a;bd?1:0}),"value")};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.zip=function(){for(var a=f.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c), -e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return function(){if(--a<1)return b.apply(this,arguments)}};b.keys=F||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)l.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a, -b.identity)};b.functions=b.methods=function(a){return b.filter(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a){h(f.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){h(f.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,c){if(a===c)return!0;var d=typeof a;if(d!= -typeof c)return!1;if(a==c)return!0;if(!a&&c||a&&!c)return!1;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return!1;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return!1;if(a.length&&a.length!==c.length)return!1;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return!1; -for(var f in a)if(!(f in c)||!b.isEqual(a[f],c[f]))return!1;return!0};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(l.call(a,c))return!1;return!0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=n||function(a){return E.call(a)==="[object Array]"};b.isArguments=function(a){return!(!a||!l.call(a,"callee"))};b.isFunction=function(a){return!(!a||!a.constructor||!a.call||!a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)}; -b.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===!0||a===!1};b.isDate=function(a){return!(!a||!a.getTimezoneOffset||!a.setUTCFullYear)};b.isRegExp=function(a){return!(!a||!a.test||!a.exec||!(a.ignoreCase||a.ignoreCase===!1))};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){p._=C;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e= -0;e/g,interpolate:/<%=([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate|| -null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return c?d(c):d};var j=function(a){this._wrapped=a};b.prototype=j.prototype;var r=function(a,c){return c?b(a).chain():a},H=function(a,c){j.prototype[a]=function(){var a=f.call(arguments);D.call(a,this._wrapped);return r(c.apply(b,a),this._chain)}};b.mixin(b);h(["pop","push","reverse","shift","sort", -"splice","unshift"],function(a){var b=i[a];j.prototype[a]=function(){b.apply(this._wrapped,arguments);return r(this._wrapped,this._chain)}});h(["concat","join","slice"],function(a){var b=i[a];j.prototype[a]=function(){return r(b.apply(this._wrapped,arguments),this._chain)}});j.prototype.chain=function(){this._chain=!0;return this};j.prototype.value=function(){return this._wrapped}})(); +// Underscore.js 1.5.1 +// http://underscorejs.org +// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. +!function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,v=e.reduce,h=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,w=i.bind,j=function(n){return n instanceof j?n:this instanceof j?(this._wrapped=n,void 0):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.5.1";var A=j.each=j.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(j.has(n,a)&&t.call(e,n[a],a,n)===r)return};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var E="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduce===v)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(E);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduceRight===h)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(E);return r},j.find=j.detect=function(n,t,r){var e;return O(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var O=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:O(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,function(n){return n[t]})},j.where=function(n,t,r){return j.isEmpty(t)?r?void 0:[]:j[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},j.findWhere=function(n,t){return j.where(n,t,!0)},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);if(!t&&j.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>e.computed&&(e={value:n,computed:a})}),e.value},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);if(!t&&j.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;ae||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.indexi;){var o=i+a>>>1;r.call(e,n[o])=0})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var M=function(){};j.bind=function(n,t){var r,e;if(w&&n.bind===w)return w.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));M.prototype=n.prototype;var u=new M;M.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},j.bindAll=function(n){var t=o.call(arguments,1);if(0===t.length)throw new Error("bindAll must be passed function names");return A(t,function(t){n[t]=j.bind(n[t],n)}),n},j.memoize=function(n,t){var r={};return t||(t=j.identity),function(){var e=t.apply(this,arguments);return j.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},j.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},j.defer=function(n){return j.delay.apply(j,[n,1].concat(o.call(arguments,1)))},j.throttle=function(n,t,r){var e,u,i,a=null,o=0;r||(r={});var c=function(){o=r.leading===!1?0:new Date,a=null,i=n.apply(e,u)};return function(){var l=new Date;o||r.leading!==!1||(o=l);var f=t-(l-o);return e=this,u=arguments,0>=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u)):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u=null;return function(){var i=this,a=arguments,o=function(){u=null,r||(e=n.apply(i,a))},c=r&&!u;return clearTimeout(u),u=setTimeout(o,t),c&&(e=n.apply(i,a)),e}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){var t=[];for(var r in n)j.has(n,r)&&t.push(n[r]);return t},j.pairs=function(n){var t=[];for(var r in n)j.has(n,r)&&t.push([r,n[r]]);return t},j.invert=function(n){var t={};for(var r in n)j.has(n,r)&&(t[n[r]]=r);return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o))return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var I={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};I.unescape=j.invert(I.escape);var T={escape:new RegExp("["+j.keys(I.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(I.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(T[n],function(t){return I[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}.call(this); +//# sourceMappingURL=underscore-min.map \ No newline at end of file From e8e37f4126201fcb3ef5c241c3b5ea1d2f3bf5ad Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Tue, 3 Sep 2013 20:42:26 +0530 Subject: [PATCH 03/18] Fallback to defaults from model.schema if present --- public/javascripts/backbone-factory.js | 45 +++++++++++++---- public/javascripts/test-setup.js | 38 ++++++++++++++ spec/javascripts/BackboneFactorySpec.js | 67 +++++++++++++++++++------ 3 files changed, 124 insertions(+), 26 deletions(-) diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index 5acec29..42ae110 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -1,3 +1,5 @@ +/*global BackboneFactory */ + // Backbone Factory JS // https://github.com/SupportBee/Backbone-Factory @@ -9,23 +11,46 @@ define: function(factory_name, klass, defaults){ + var schema = klass.prototype.schema, + schema_defaults = {}, + model_defaults; + // Check for arguments' sanity if(factory_name.match(/[^\w-_]+/)){ throw "Factory name should not contain spaces or other funky characters"; } - if(defaults === undefined) defaults = function(){return {}}; + model_defaults = _.result( klass.prototype, 'defaults' ); + + if(defaults === undefined) defaults = function(){return {};} + + if ( schema ) { + schema_defaults = _.object( + _( schema ).keys(), + _( schema ).chain() + .values() + .pluck( 'default' ) + .value() + ); + } // The object creator this.factories[factory_name] = function(options){ - if(options === undefined) options = function(){return {}}; - arguments = _.extend({}, {id: BackboneFactory.next("_" + factory_name + "_id")}, defaults.call(), options.call()); - return new klass(arguments); + if(options === undefined) options = function(){return {};}; + var attributes = _.extend( + {}, + { id: BackboneFactory.next("_" + factory_name + "_id") }, + schema_defaults, + model_defaults, + defaults.call(), + options.call() + ); + return new klass(attributes); }; // Lets define a sequence for id BackboneFactory.define_sequence("_"+ factory_name +"_id", function(n){ - return n + return n; }); }, @@ -33,13 +58,13 @@ if(this.factories[factory_name] === undefined){ throw "Factory with name " + factory_name + " does not exist"; } - return this.factories[factory_name].apply(null, [options]); + return this.factories[factory_name].apply(null, [options]); }, define_sequence: function(sequence_name, callback){ - this.sequences[sequence_name] = {} + this.sequences[sequence_name] = {}; this.sequences[sequence_name]['counter'] = 0; - this.sequences[sequence_name]['callback'] = callback; + this.sequences[sequence_name]['callback'] = callback; }, next: function(sequence_name){ @@ -47,7 +72,7 @@ throw "Sequence with name " + sequence_name + " does not exist"; } this.sequences[sequence_name]['counter'] += 1; - return this.sequences[sequence_name]['callback'].apply(null, [this.sequences[sequence_name]['counter']]); //= callback; + return this.sequences[sequence_name]['callback'].apply(null, [this.sequences[sequence_name]['counter']]); //= callback; } - } + }; })(); diff --git a/public/javascripts/test-setup.js b/public/javascripts/test-setup.js index 531e20a..805ed33 100644 --- a/public/javascripts/test-setup.js +++ b/public/javascripts/test-setup.js @@ -7,6 +7,24 @@ var User = Backbone.Model.extend({ }); +var UserWithSchema = Backbone.Model.extend({ + + name: null, + email: null, + + schema: { + name: { + type: 'string', + default: 'Backbone User' + }, + email: { + type: 'string', + default: '' + } + } + +}); + var Post = Backbone.Model.extend({ defaults: { @@ -14,3 +32,23 @@ var Post = Backbone.Model.extend({ } }); + + +var PostWithSchema = Backbone.Model.extend({ + + defaults: { + title: 'Default Title' + }, + + schema: { + title: { + type: 'string', + default: 'Default value from schema' + }, + body: { + type: 'string', + default: 'Default body' + } + } + +}); diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index 3ba09c2..a707baa 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -1,10 +1,11 @@ +/*global sinon, describe, beforeEach, afterEach, it, expect, BackboneFactory, User, UserWithSchema, Post, PostWithSchema */ describe("Backbone Factory", function() { describe("Defining and using Sequences", function(){ beforeEach(function() { - var emailSequence = BackboneFactory.define_sequence('email', function(n){ - return "person"+n+"@example.com"; + this.emailSequence = BackboneFactory.define_sequence('email', function(n){ + return "person"+n+"@example.com"; }); }); @@ -19,7 +20,7 @@ describe("Backbone Factory", function() { beforeEach(function() { var emailSequence = BackboneFactory.define_sequence('person_email', function(n){ - return "person"+n+"@example.com"; + return "person"+n+"@example.com"; }); var postFactory = BackboneFactory.define('post', Post, function(){ return { @@ -38,19 +39,19 @@ describe("Backbone Factory", function() { this.postObject = BackboneFactory.create('post'); this.userObject = BackboneFactory.create('user'); }); - + it("return an instance of the Backbone Object requested", function() { expect(this.postObject instanceof Post).toBeTruthy(); expect(this.userObject instanceof User).toBeTruthy(); }); - + // Not sure if this test is needed. But what the hell! it("should preserve the defaults if not overriden", function() { expect(this.postObject.get('title')).toBe('Default Title'); }); - + it("should use the defaults supplied when creating objects", function() { expect(this.userObject.get('name')).toBe('Backbone User'); @@ -63,8 +64,8 @@ describe("Backbone Factory", function() { }); it("should work if other factories are passed", function(){ - expect(this.postObject.get('author') instanceof User).toBeTruthy(); - }) + expect(this.postObject.get('author') instanceof User).toBeTruthy(); + }); it("should override defaults if arguments are passed on creation", function(){ var userWithEmail = BackboneFactory.create('user', function(){ @@ -84,13 +85,13 @@ describe("Backbone Factory", function() { var secondID = BackboneFactory.create('user').id; expect(secondID).toBe(firstID + 1); }); - + describe("Error Messages", function() { it("should throw an error if factory_name is not proper", function() { expect(function(){BackboneFactory.define('wrong name', Post)}).toThrow("Factory name should not contain spaces or other funky characters"); }); - + it("should not throw an error if factory_name has a hyphen", function() { expect(function(){BackboneFactory.define('okay-name', Post)}).not.toThrow(); }); @@ -102,10 +103,44 @@ describe("Backbone Factory", function() { it("should throw an error if you try to use an undefined sequence", function() { expect(function(){BackboneFactory.next('undefined_sequence')}).toThrow("Sequence with name undefined_sequence does not exist"); }); - - }); - - }); - -}); + }); + + }); + + describe("Defining and using Factories with Schema", function() { + + beforeEach(function() { + var emailSequence = BackboneFactory.define_sequence('person_email', function(n){ + return "person"+n+"@example.com"; + }); + var postFactory = BackboneFactory.define('post_with_schema', PostWithSchema ); + var userFactory = BackboneFactory.define('user_with_schema', UserWithSchema, function() { + return { + email: BackboneFactory.next('person_email') + }; + }); + this.postObject = BackboneFactory.create('post_with_schema'); + this.userObject = BackboneFactory.create('user'); + }); + + + it ("should create model using schema if present", function() { + expect(this.userObject.get('name')).toEqual('Backbone User'); + }); + + it ("should get email using sequence", function() { + expect(this.userObject.get('email')).toEqual('person1@example.com'); + }); + + it ("defaults option should override default from schema", function() { + expect(this.postObject.get('title')).toEqual('Default Title'); + }); + + it ("should fallback to schema.default", function() { + expect(this.postObject.get('body')).toEqual('Default body'); + }); + + }); + +}); From a253d7e9619aa499e0392dc5fe0ac83fa3e10b1e Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Tue, 3 Sep 2013 20:44:32 +0530 Subject: [PATCH 04/18] Fixing code style to match original code --- spec/javascripts/BackboneFactorySpec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index a707baa..3914be5 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -125,19 +125,19 @@ describe("Backbone Factory", function() { }); - it ("should create model using schema if present", function() { + it("should create model using schema if present", function() { expect(this.userObject.get('name')).toEqual('Backbone User'); }); - it ("should get email using sequence", function() { + it("should get email using sequence", function() { expect(this.userObject.get('email')).toEqual('person1@example.com'); }); - it ("defaults option should override default from schema", function() { + it("defaults option should override default from schema", function() { expect(this.postObject.get('title')).toEqual('Default Title'); }); - it ("should fallback to schema.default", function() { + it("should fallback to schema.default", function() { expect(this.postObject.get('body')).toEqual('Default body'); }); From 3e6099ce5518f621f22a49d3adfac9981ccd2980 Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Wed, 4 Sep 2013 15:14:41 +0530 Subject: [PATCH 05/18] Handling related fields in schema --- public/javascripts/backbone-factory.js | 53 +++++++++++++++++-------- public/javascripts/test-setup.js | 4 ++ spec/javascripts/BackboneFactorySpec.js | 24 ++++++++--- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index 42ae110..bbe5fde 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -4,43 +4,62 @@ // https://github.com/SupportBee/Backbone-Factory (function(){ + + function getFactoryName( constructor ) { + var keys = _.keys( BackboneFactory.klasses ), + values = _.values( BackboneFactory.klasses ); + return keys[ values.indexOf( constructor ) ]; + } + window.BackboneFactory = { factories: {}, sequences: {}, + klasses: {}, define: function(factory_name, klass, defaults){ - var schema = klass.prototype.schema, - schema_defaults = {}, - model_defaults; - // Check for arguments' sanity if(factory_name.match(/[^\w-_]+/)){ throw "Factory name should not contain spaces or other funky characters"; } - model_defaults = _.result( klass.prototype, 'defaults' ); - if(defaults === undefined) defaults = function(){return {};} - if ( schema ) { - schema_defaults = _.object( - _( schema ).keys(), - _( schema ).chain() - .values() - .pluck( 'default' ) - .value() - ); - } - // The object creator + this.klasses[factory_name] = klass; this.factories[factory_name] = function(options){ if(options === undefined) options = function(){return {};}; + + var schema = klass.prototype.schema, + schema_defaults = {}, + model_defaults, + related_attrs = {}; + + model_defaults = _.result(klass.prototype, 'defaults'); + + if ( schema ) { + schema_defaults = _.object( + _( schema ).keys(), + _( schema ).chain() + .values() + .pluck( 'default' ) + .value() + ); + + _(schema).each(function(attr, key) { + if(attr.type == 'related' && attr.related_to) { + related_attrs[key] = BackboneFactory.create( + getFactoryName(attr.related_to) + ); + } + }); + } + var attributes = _.extend( - {}, { id: BackboneFactory.next("_" + factory_name + "_id") }, schema_defaults, + related_attrs, model_defaults, defaults.call(), options.call() diff --git a/public/javascripts/test-setup.js b/public/javascripts/test-setup.js index 805ed33..111da18 100644 --- a/public/javascripts/test-setup.js +++ b/public/javascripts/test-setup.js @@ -48,6 +48,10 @@ var PostWithSchema = Backbone.Model.extend({ body: { type: 'string', default: 'Default body' + }, + author: { + type: 'related', + related_to: UserWithSchema } } diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index 3914be5..6be357b 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -120,25 +120,37 @@ describe("Backbone Factory", function() { email: BackboneFactory.next('person_email') }; }); - this.postObject = BackboneFactory.create('post_with_schema'); - this.userObject = BackboneFactory.create('user'); }); it("should create model using schema if present", function() { - expect(this.userObject.get('name')).toEqual('Backbone User'); + var user = BackboneFactory.create('user_with_schema'); + expect(user.get('name')).toEqual('Backbone User'); }); it("should get email using sequence", function() { - expect(this.userObject.get('email')).toEqual('person1@example.com'); + var user = BackboneFactory.create('user_with_schema'); + expect(user.get('email')).toEqual('person1@example.com'); }); it("defaults option should override default from schema", function() { - expect(this.postObject.get('title')).toEqual('Default Title'); + var post = BackboneFactory.create('post_with_schema'); + expect(post.get('title')).toEqual('Default Title'); + }); + + it("should fallback to schema.default", function() { + var post = BackboneFactory.create('post_with_schema'); + expect(post.get('body')).toEqual('Default body'); }); it("should fallback to schema.default", function() { - expect(this.postObject.get('body')).toEqual('Default body'); + var post = BackboneFactory.create('post_with_schema'); + expect(post.get('body')).toEqual('Default body'); + }); + + it("should create related object from schema", function() { + var post = BackboneFactory.create('post_with_schema'); + expect(post.get('author') instanceof UserWithSchema).toBeTruthy(); }); }); From 78dc0d97ac130b1e128dc2d537a1bff2469c9335 Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Wed, 4 Sep 2013 22:10:40 +0530 Subject: [PATCH 06/18] Factory for creating collections --- public/javascripts/backbone-factory.js | 69 +++++++++++++++++++------ public/javascripts/test-setup.js | 23 +++++++++ spec/javascripts/BackboneFactorySpec.js | 53 +++++++++++++++++-- 3 files changed, 125 insertions(+), 20 deletions(-) diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index bbe5fde..1d12a39 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -5,17 +5,27 @@ (function(){ - function getFactoryName( constructor ) { - var keys = _.keys( BackboneFactory.klasses ), - values = _.values( BackboneFactory.klasses ); - return keys[ values.indexOf( constructor ) ]; + function get_factory_name(klass){ + var keys = _.keys(BackboneFactory.model_klasses), + values = _.values(BackboneFactory.model_klasses); + return keys[values.indexOf(klass)]; + } + + function get_collection_name(klass){ + var keys = _.keys(BackboneFactory.collection_klasses), + values = _.values(BackboneFactory.collection_klasses); + return keys[values.indexOf(klass)]; } window.BackboneFactory = { factories: {}, + model_klasses: {}, + + collections: {}, + collection_klasses: {}, + sequences: {}, - klasses: {}, define: function(factory_name, klass, defaults){ @@ -27,9 +37,9 @@ if(defaults === undefined) defaults = function(){return {};} // The object creator - this.klasses[factory_name] = klass; - this.factories[factory_name] = function(options){ - if(options === undefined) options = function(){return {};}; + this.model_klasses[factory_name] = klass; + this.factories[factory_name] = function(attrs_generator, options){ + if(attrs_generator === undefined) attrs_generator = function(){return {};}; var schema = klass.prototype.schema, schema_defaults = {}, @@ -48,10 +58,15 @@ ); _(schema).each(function(attr, key) { + var name; if(attr.type == 'related' && attr.related_to) { - related_attrs[key] = BackboneFactory.create( - getFactoryName(attr.related_to) - ); + name = get_factory_name(attr.related_to); + if(name){ + related_attrs[key] = BackboneFactory.create(name); + }else{ + name = get_collection_name(attr.related_to); + related_attrs[key] = BackboneFactory.create_collection(name); + } } }); } @@ -62,9 +77,9 @@ related_attrs, model_defaults, defaults.call(), - options.call() + attrs_generator.call() ); - return new klass(attributes); + return new klass(attributes, options); }; // Lets define a sequence for id @@ -73,11 +88,11 @@ }); }, - create: function(factory_name, options){ + create: function(factory_name, attrs_generator, options){ if(this.factories[factory_name] === undefined){ throw "Factory with name " + factory_name + " does not exist"; } - return this.factories[factory_name].apply(null, [options]); + return this.factories[factory_name].call(null, attrs_generator, options); }, define_sequence: function(sequence_name, callback){ @@ -92,6 +107,30 @@ } this.sequences[sequence_name]['counter'] += 1; return this.sequences[sequence_name]['callback'].apply(null, [this.sequences[sequence_name]['counter']]); //= callback; + }, + + define_collection: function(collection_name, klass, default_size, default_options) { + var factory_name = get_factory_name(klass.prototype.model); + + this.collection_klasses[collection_name] = klass; + this.collections[collection_name] = function(size, attrs_generator, options) { + var models = []; + if(typeof size!='number') size = default_size; + options = options || default_options || {}; + + for(var i=0; i Date: Thu, 5 Sep 2013 14:02:15 +0530 Subject: [PATCH 07/18] Whitespace changes & coding style fixes --- README.mkd | 16 ++++++---------- public/javascripts/backbone-factory.js | 18 +++++++++--------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/README.mkd b/README.mkd index 45cd784..4803151 100644 --- a/README.mkd +++ b/README.mkd @@ -4,15 +4,15 @@ Backbone Factory Introduction ------------ -Backbone Factory is a small javascript library for creating [Backbone.js](http://documentcloud.github.com/backbone/) objects for testing your code. It has no external dependency. +Backbone Factory is a small javascript library for creating [Backbone.js](http://documentcloud.github.com/backbone/) objects for testing your code. It has no external dependency. -The API is heavily inspired by the awesome [Factory Girl](https://github.com/thoughtbot/factory_girl). +The API is heavily inspired by the awesome [Factory Girl](https://github.com/thoughtbot/factory_girl). Installation ------------ -To use it, just [download](https://github.com/SupportBee/Backbone-Factory/raw/master/public/javascripts/backbone-factory.js) the file and include it in your testing setup. +To use it, just [download](https://github.com/SupportBee/Backbone-Factory/raw/master/public/javascripts/backbone-factory.js) the file and include it in your testing setup. Usage ----- @@ -46,7 +46,7 @@ var userFactory = BackboneFactory.define('user', User); ### Using Factories -To use these factories, +To use these factories, ```javscript this.postObject = BackboneFactory.create('post'); @@ -56,11 +56,11 @@ this.userObject = BackboneFactory.create('user'); This will create objects using the [defaults](http://documentcloud.github.com/backbone/#Model-defaults) you have in your class definitions. -### Defining Sequences +### Defining Sequences ```javascript var emailSequence = BackboneFactory.define_sequence('email', function(n){ - return "person"+n+"@example.com"; + return "person"+n+"@example.com"; }); ``` @@ -129,7 +129,3 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - - diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index 1d12a39..b473854 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -48,18 +48,18 @@ model_defaults = _.result(klass.prototype, 'defaults'); - if ( schema ) { + if(schema){ schema_defaults = _.object( - _( schema ).keys(), - _( schema ).chain() + _(schema).keys(), + _(schema).chain() .values() - .pluck( 'default' ) + .pluck('default') .value() ); - _(schema).each(function(attr, key) { + _(schema).each(function(attr, key){ var name; - if(attr.type == 'related' && attr.related_to) { + if(attr.type == 'related' && attr.related_to){ name = get_factory_name(attr.related_to); if(name){ related_attrs[key] = BackboneFactory.create(name); @@ -109,16 +109,16 @@ return this.sequences[sequence_name]['callback'].apply(null, [this.sequences[sequence_name]['counter']]); //= callback; }, - define_collection: function(collection_name, klass, default_size, default_options) { + define_collection: function(collection_name, klass, default_size, default_options){ var factory_name = get_factory_name(klass.prototype.model); this.collection_klasses[collection_name] = klass; - this.collections[collection_name] = function(size, attrs_generator, options) { + this.collections[collection_name] = function(size, attrs_generator, options){ var models = []; if(typeof size!='number') size = default_size; options = options || default_options || {}; - for(var i=0; i Date: Thu, 5 Sep 2013 14:02:39 +0530 Subject: [PATCH 08/18] Adding testem config --- testem.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 testem.json diff --git a/testem.json b/testem.json new file mode 100644 index 0000000..8ad4702 --- /dev/null +++ b/testem.json @@ -0,0 +1,11 @@ +{ + "framework": "jasmine", + "launch_in_dev": ["PhantomJS"], + "src_files": [ + "public/javascripts/underscore-min.js", + "public/javascripts/backbone-min.js", + "public/javascripts/test-setup.js", + "public/javascripts/backbone-factory.js", + "spec/javascripts/BackboneFactorySpec.js" + ] +} From b1a16e974c31422f9dab611961823b159e0114bd Mon Sep 17 00:00:00 2001 From: Raghu Date: Thu, 5 Sep 2013 14:34:56 +0530 Subject: [PATCH 09/18] testing support for models without schema --- README.mkd | 66 +++++++++++++++++++++---- public/javascripts/test-setup.js | 4 ++ spec/javascripts/BackboneFactorySpec.js | 12 ++++- 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/README.mkd b/README.mkd index 4803151..c917835 100644 --- a/README.mkd +++ b/README.mkd @@ -12,7 +12,8 @@ The API is heavily inspired by the awesome [Factory Girl](https://github.com/tho Installation ------------ -To use it, just [download](https://github.com/SupportBee/Backbone-Factory/raw/master/public/javascripts/backbone-factory.js) the file and include it in your testing setup. +To use it, just [download](https://github.com/recruiterbox/Backbone-Factory/raw/master/public/javascripts/backbone-factory.js) the file and include it in your testing setup. + Usage ----- @@ -21,8 +22,10 @@ Lets say you have two Backbone models, Post and User ```javascript var User = Backbone.Model.extend({ - name: null, - email: null + defaults: { + name: 'Raghu', + email: 'raghu@example.com' + } }); @@ -40,8 +43,8 @@ var Post = Backbone.Model.extend({ To define factories for them ```javascript -var postFactory = BackboneFactory.define('post', Post); -var userFactory = BackboneFactory.define('user', User); +BackboneFactory.define('post', Post); +BackboneFactory.define('user', User); ``` ### Using Factories @@ -49,8 +52,8 @@ var userFactory = BackboneFactory.define('user', User); To use these factories, ```javscript -this.postObject = BackboneFactory.create('post'); -this.userObject = BackboneFactory.create('user'); +postObject = BackboneFactory.create('post'); +userObject = BackboneFactory.create('user'); ``` This will create objects using the [defaults](http://documentcloud.github.com/backbone/#Model-defaults) you have in your class definitions. @@ -59,8 +62,9 @@ This will create objects using the [defaults](http://documentcloud.github.com/ba ### Defining Sequences ```javascript -var emailSequence = BackboneFactory.define_sequence('email', function(n){ - return "person"+n+"@example.com"; +BackboneFactory.define_sequence('email', function(n){ + return "person"+n+"@example.com"; +>>>>>>> Stashed changes }); ``` @@ -73,7 +77,7 @@ var email = BackboneFactory.next('email') // person1@example.com ### Defining Factories with defaults ```javascript -var userFactory = BackboneFactory.define('user', User, function(){ +BackboneFactory.define('user', User, function(){ return { name : 'Backbone User', email: BackboneFactory.next('email') @@ -92,6 +96,48 @@ var userWithEmail = BackboneFactory.create('user', function(){ }); ``` +### Schema Support + +If backbone models define a schema, schema is used to set default values. Nested models are also taken care of. + +```javascript + + +var PostWithSchema = Backbone.Model.extend({ + + schema: { + title: { + type: 'string', + default: 'Default value from schema' + }, + body: { + type: 'string', + default: 'Default body' + }, + author: { + type: 'related', + related_to: User + } + } + +}); + +BackboneFactory.define('post_with_schema', PostWithSchema); +var post = BackboneFactory.create('post_with_schema'); + +//Post title will be picked up from schema +console.log(post.get('title'); //Default value from schema + +//Author was created automatically using the schema +var author = post.get('author'); +console.log(author.get('name'); //Raghu + + + +``` + +If defaults and schema are both present, default values from the backbone model take precedence over the scheme defaults. + Contributing ------------ diff --git a/public/javascripts/test-setup.js b/public/javascripts/test-setup.js index 91acace..ae4789e 100644 --- a/public/javascripts/test-setup.js +++ b/public/javascripts/test-setup.js @@ -72,6 +72,10 @@ var PostWithSchema = Backbone.Model.extend({ type: 'related', related_to: UserWithSchema }, + author_without_schema: { + type: 'related', + related_to: User + }, comments: { type: 'related', related_to: Comments diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index 813be7c..81024e7 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -150,11 +150,19 @@ describe("Backbone Factory", function() { expect(post.get('body')).toEqual('Default body'); }); - it("should create related Model field from schema", function() { + describe("Related Model", function(){ + it("should create related Model field from schema", function() { + var post = BackboneFactory.create('post_with_schema'); + expect(post.get('author') instanceof UserWithSchema).toBeTruthy(); + }); + }); + + it("should create related Model that has no schema", function() { var post = BackboneFactory.create('post_with_schema'); - expect(post.get('author') instanceof UserWithSchema).toBeTruthy(); + expect(post.get('author_without_schema') instanceof User).toBeTruthy(); }); + describe("Related Collection", function() { it("should be created from schema", function() { From 7c80ec7c60785161b8cf8513d72114523e575733 Mon Sep 17 00:00:00 2001 From: Raghu Date: Thu, 5 Sep 2013 15:22:27 +0530 Subject: [PATCH 10/18] Documented functionality around nested models / collections --- README.mkd | 146 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 108 insertions(+), 38 deletions(-) diff --git a/README.mkd b/README.mkd index c917835..5fa567e 100644 --- a/README.mkd +++ b/README.mkd @@ -4,7 +4,7 @@ Backbone Factory Introduction ------------ -Backbone Factory is a small javascript library for creating [Backbone.js](http://documentcloud.github.com/backbone/) objects for testing your code. It has no external dependency. +Backbone Factory is a small javascript library for creating [Backbone.js](http://documentcloud.github.com/backbone/) objects for testing your code. We have extended [this](https://github.com/SupportBee/Backbone-Factory) library to provide support from nested models/collections. This is a strict superset of the original authors functionality. It has no external dependency. The API is heavily inspired by the awesome [Factory Girl](https://github.com/thoughtbot/factory_girl). @@ -13,7 +13,6 @@ Installation ------------ To use it, just [download](https://github.com/recruiterbox/Backbone-Factory/raw/master/public/javascripts/backbone-factory.js) the file and include it in your testing setup. - Usage ----- @@ -51,58 +50,49 @@ BackboneFactory.define('user', User); To use these factories, -```javscript -postObject = BackboneFactory.create('post'); -userObject = BackboneFactory.create('user'); +```javascript +var postObject = BackboneFactory.create('post'); +var userObject = BackboneFactory.create('user'); ``` -This will create objects using the [defaults](http://documentcloud.github.com/backbone/#Model-defaults) you have in your class definitions. - - -### Defining Sequences - +This will create objects using the [defaults](http://documentcloud.github.com/backbone/#Model-defaults) you have in your class definitions. It is easy to override the defaults when creating an object ```javascript -BackboneFactory.define_sequence('email', function(n){ - return "person"+n+"@example.com"; ->>>>>>> Stashed changes - }); + +var userObject = BackboneFactory.create('user', function(){ + return { + name: "Custom Name", + email: "custom@email.com" + }; + }); ``` -### Using Sequences +### Defining and using Collections + +To define factories for collections ```javascript -var email = BackboneFactory.next('email') // person1@example.com -``` +var Posts = Backbone.Collection.extend({ + model: Post +}); +var Users = Backbone.Collection.extend({ + model: User +}); -### Defining Factories with defaults +BackboneFactory.define_collection('posts', Posts, 3); //Third arugement is the default size of the collection +BackboneFactory.define_collection('users', Users, 4); -```javascript -BackboneFactory.define('user', User, function(){ - return { - name : 'Backbone User', - email: BackboneFactory.next('email') - }; - } - ); -``` +var postsCollection = BackboneFactory.create('posts'); //Creates 3 posts +var usersCollection = BackboneFactory.create('users',2) //Creates only 2 users overriding the default of 4 -### Overriding defaults when creating objects +``` -```javascript -var userWithEmail = BackboneFactory.create('user', function(){ - return { - email: 'overriden@example.com' - }; - }); - ``` ### Schema Support -If backbone models define a schema, schema is used to set default values. Nested models are also taken care of. +If your backbone models define a schema, it is used to set default values. Nested models are also supported. ```javascript - var PostWithSchema = Backbone.Model.extend({ schema: { @@ -122,6 +112,7 @@ var PostWithSchema = Backbone.Model.extend({ }); + BackboneFactory.define('post_with_schema', PostWithSchema); var post = BackboneFactory.create('post_with_schema'); @@ -132,11 +123,90 @@ console.log(post.get('title'); //Default value from schema var author = post.get('author'); console.log(author.get('name'); //Raghu +``` +Cool! isn't it? If defaults and schema are both present, default values from the backbone model take precedence over the scheme defaults. +Now, lets complicate this a bit further. + +```javascript +var Comment = Backbone.Model.extend({ + + schema: { + msg: { + type: 'string', + default: 'Default comment msg' + } + } + +}); + +var Comments = Backbone.Collection.extend({ + model: Comment +}); + +var PostWithSchema = Backbone.Model.extend({ + + schema: { + title: { + type: 'string', + default: 'Default value from schema' + }, + body: { + type: 'string', + default: 'Default body' + }, + author: { + type: 'related', + related_to: User + } + comments: { + type: 'related', + related_to: Comments + } + } +}); + + +BackboneFactory.define('post_with_schema', PostWithSchema); +BackboneFactory.define('comments', Comments, 2); + +var post = BackboneFactory.create('post_with_schema'); +var comments = post.get('comments'); +console.log(comments.size()) //gives a value of 2 +``` +Its very easy to change the size of the collection of comments + +```javascript +var post = BackboneFactory.create('post_with_schema', function(){ + return { comments: BackboneFactory.create_collection('comments', 4) }); +var comments = post.get('comments'); +console.log(comments.size()) //gives a value of 4 +``` +If a comments BackboneFactory is not defined, an empty collection of comments is created when a post is created. +### Dynamically generating attribute values: Sequences +Often, we'd like to generate unique values for model attributes when new objects are created. For example, we may want the username/email of a user to be always unique. We can use sequences for this. +```javascript +BackboneFactory.define_sequence('email', function(n){ + return "person"+n+"@example.com"; + }); + +var email = BackboneFactory.next('email') // person1@example.com ``` -If defaults and schema are both present, default values from the backbone model take precedence over the scheme defaults. +### Defining Factories with Sequences + +```javascript +BackboneFactory.define('user', User, function(){ + return { + name : 'Backbone User', + email: BackboneFactory.next('email') + }; + } + ); +var user = BackboneFactory.create('user); +console.log(user.get('email') // person2@example.com +``` Contributing ------------ From 7d2e3fb5ae7f89e8c56b05f84764cf18568263cd Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Thu, 5 Sep 2013 15:07:49 +0530 Subject: [PATCH 11/18] Moving test case inside appropriate describe block --- spec/javascripts/BackboneFactorySpec.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index 81024e7..0acbdd7 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -151,17 +151,17 @@ describe("Backbone Factory", function() { }); describe("Related Model", function(){ - it("should create related Model field from schema", function() { + it("should be created from schema if exists", function() { var post = BackboneFactory.create('post_with_schema'); expect(post.get('author') instanceof UserWithSchema).toBeTruthy(); }); - }); - it("should create related Model that has no schema", function() { - var post = BackboneFactory.create('post_with_schema'); - expect(post.get('author_without_schema') instanceof User).toBeTruthy(); - }); + it("should be created from schema even the related model has no schema", function() { + var post = BackboneFactory.create('post_with_schema'); + expect(post.get('author_without_schema') instanceof User).toBeTruthy(); + }); + }); describe("Related Collection", function() { From 375ddd5e89b3f4da4405685099784d056a0bec7b Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Thu, 5 Sep 2013 15:12:18 +0530 Subject: [PATCH 12/18] testing multiple factories for same constructor while creating related fields from schema, the first factory matching the constructor is used --- spec/javascripts/BackboneFactorySpec.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index 0acbdd7..d85508f 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -161,6 +161,12 @@ describe("Backbone Factory", function() { expect(post.get('author_without_schema') instanceof User).toBeTruthy(); }); + it("should work even when there are multiple factories for the same constructor", function(){ + BackboneFactory.define('another_user_with_schema', UserWithSchema); + var post = BackboneFactory.create('post_with_schema'); + expect(post.get('author') instanceof UserWithSchema).toBeTruthy(); + }); + }); describe("Related Collection", function() { From eb81d05a9c4ce45e7fc810ab16b5e51aded7aff6 Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Thu, 5 Sep 2013 15:38:18 +0530 Subject: [PATCH 13/18] Creating related fiels from schema even if there is no corresponding factory --- public/javascripts/backbone-factory.js | 8 +++---- public/javascripts/test-setup.js | 4 ++++ spec/javascripts/BackboneFactorySpec.js | 28 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index b473854..2ba3d09 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -60,12 +60,12 @@ _(schema).each(function(attr, key){ var name; if(attr.type == 'related' && attr.related_to){ - name = get_factory_name(attr.related_to); - if(name){ + if(name = get_factory_name(attr.related_to)){ related_attrs[key] = BackboneFactory.create(name); - }else{ - name = get_collection_name(attr.related_to); + }else if(name = get_collection_name(attr.related_to)){ related_attrs[key] = BackboneFactory.create_collection(name); + }else{ + related_attrs[key] = new attr.related_to(); } } }); diff --git a/public/javascripts/test-setup.js b/public/javascripts/test-setup.js index ae4789e..a09f624 100644 --- a/public/javascripts/test-setup.js +++ b/public/javascripts/test-setup.js @@ -40,6 +40,10 @@ var Comment = Backbone.Model.extend({ msg: { type: 'string', default: 'Default comment msg' + }, + author: { + type: 'related', + related_to: User } } diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index d85508f..57958f1 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -167,6 +167,20 @@ describe("Backbone Factory", function() { expect(post.get('author') instanceof UserWithSchema).toBeTruthy(); }); + it("should be created even if there is no factory", function() { + var CommentCopy = Comment; + CommentCopy.prototype.schema = _.extend(Comment.prototype.schema, { + author: { + type: 'related', + related_to: Backbone.Model + } + }); + BackboneFactory.define('comment', CommentCopy); + var comment = BackboneFactory.create('comment'); + expect(comment.get('author') instanceof Backbone.Model).toBeTruthy(); + expect(comment.get('author') instanceof User).toBeFalsy(); + }); + }); describe("Related Collection", function() { @@ -208,6 +222,20 @@ describe("Backbone Factory", function() { })).toBeTruthy(); }); + it("should be created even if there is no factory", function() { + var PostCopy = PostWithSchema; + PostCopy.prototype.schema = _.extend(PostWithSchema.prototype.schema, { + comments: { + type: 'related', + related_to: Backbone.Collection + } + }); + BackboneFactory.define('post', PostCopy); + var post = BackboneFactory.create('post'); + expect(post.get('comments') instanceof Backbone.Collection).toBeTruthy(); + expect(post.get('comments') instanceof Comments).toBeFalsy(); + }); + }); }); From 19ac92eff8b6e48503a3c84050fe571b7e931e84 Mon Sep 17 00:00:00 2001 From: Raghu Date: Thu, 12 Sep 2013 15:09:17 +0530 Subject: [PATCH 14/18] renamed schema attribute related_to to constructor --- README.mkd | 6 +++--- public/javascripts/backbone-factory.js | 9 +++++---- public/javascripts/test-setup.js | 6 +++--- spec/javascripts/BackboneFactorySpec.js | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.mkd b/README.mkd index 5fa567e..3233304 100644 --- a/README.mkd +++ b/README.mkd @@ -106,7 +106,7 @@ var PostWithSchema = Backbone.Model.extend({ }, author: { type: 'related', - related_to: User + constructor: User } } @@ -156,11 +156,11 @@ var PostWithSchema = Backbone.Model.extend({ }, author: { type: 'related', - related_to: User + constructor: User } comments: { type: 'related', - related_to: Comments + constructor: Comments } } }); diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index 2ba3d09..c7542a9 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -59,16 +59,17 @@ _(schema).each(function(attr, key){ var name; - if(attr.type == 'related' && attr.related_to){ - if(name = get_factory_name(attr.related_to)){ + if(attr.type == 'related' && attr.constructor){ + if(name = get_factory_name(attr.constructor)){ related_attrs[key] = BackboneFactory.create(name); - }else if(name = get_collection_name(attr.related_to)){ + }else if(name = get_collection_name(attr.constructor)){ related_attrs[key] = BackboneFactory.create_collection(name); }else{ - related_attrs[key] = new attr.related_to(); + related_attrs[key] = new attr.constructor(); } } }); + } var attributes = _.extend( diff --git a/public/javascripts/test-setup.js b/public/javascripts/test-setup.js index a09f624..5cae866 100644 --- a/public/javascripts/test-setup.js +++ b/public/javascripts/test-setup.js @@ -74,15 +74,15 @@ var PostWithSchema = Backbone.Model.extend({ }, author: { type: 'related', - related_to: UserWithSchema + constructor: UserWithSchema }, author_without_schema: { type: 'related', - related_to: User + constructor: User }, comments: { type: 'related', - related_to: Comments + constructor: Comments } } diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index 57958f1..d3f0b10 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -172,7 +172,7 @@ describe("Backbone Factory", function() { CommentCopy.prototype.schema = _.extend(Comment.prototype.schema, { author: { type: 'related', - related_to: Backbone.Model + constructor: Backbone.Model } }); BackboneFactory.define('comment', CommentCopy); @@ -227,7 +227,7 @@ describe("Backbone Factory", function() { PostCopy.prototype.schema = _.extend(PostWithSchema.prototype.schema, { comments: { type: 'related', - related_to: Backbone.Collection + constructor: Backbone.Collection } }); BackboneFactory.define('post', PostCopy); From 1a77aba370c676008c1f3f67111b52db3975772d Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Fri, 27 Sep 2013 16:11:21 +0530 Subject: [PATCH 15/18] renaming constructor to '_constructor' --- public/javascripts/backbone-factory.js | 8 ++++---- public/javascripts/test-setup.js | 6 +++--- spec/javascripts/BackboneFactorySpec.js | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index c7542a9..891c157 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -59,13 +59,13 @@ _(schema).each(function(attr, key){ var name; - if(attr.type == 'related' && attr.constructor){ - if(name = get_factory_name(attr.constructor)){ + if(attr.type == 'related' && attr._constructor){ + if(name = get_factory_name(attr._constructor)){ related_attrs[key] = BackboneFactory.create(name); - }else if(name = get_collection_name(attr.constructor)){ + }else if(name = get_collection_name(attr._constructor)){ related_attrs[key] = BackboneFactory.create_collection(name); }else{ - related_attrs[key] = new attr.constructor(); + related_attrs[key] = new attr._constructor(); } } }); diff --git a/public/javascripts/test-setup.js b/public/javascripts/test-setup.js index 5cae866..ed7e9e1 100644 --- a/public/javascripts/test-setup.js +++ b/public/javascripts/test-setup.js @@ -74,15 +74,15 @@ var PostWithSchema = Backbone.Model.extend({ }, author: { type: 'related', - constructor: UserWithSchema + _constructor: UserWithSchema }, author_without_schema: { type: 'related', - constructor: User + _constructor: User }, comments: { type: 'related', - constructor: Comments + _constructor: Comments } } diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index d3f0b10..0e372e4 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -172,7 +172,7 @@ describe("Backbone Factory", function() { CommentCopy.prototype.schema = _.extend(Comment.prototype.schema, { author: { type: 'related', - constructor: Backbone.Model + _constructor: Backbone.Model } }); BackboneFactory.define('comment', CommentCopy); @@ -227,7 +227,7 @@ describe("Backbone Factory", function() { PostCopy.prototype.schema = _.extend(PostWithSchema.prototype.schema, { comments: { type: 'related', - constructor: Backbone.Collection + _constructor: Backbone.Collection } }); BackboneFactory.define('post', PostCopy); From af49564c6cf863a0b0bec9b8f29fc9d697c8765f Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Sat, 28 Sep 2013 01:24:22 +0530 Subject: [PATCH 16/18] Fixing issues with default value being undefined + cleaning up test cases --- public/javascripts/backbone-factory.js | 32 +++++++---------- public/javascripts/test-setup.js | 2 +- spec/javascripts/BackboneFactorySpec.js | 47 +++++++++++++++---------- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index 891c157..05cc20f 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -42,30 +42,26 @@ if(attrs_generator === undefined) attrs_generator = function(){return {};}; var schema = klass.prototype.schema, - schema_defaults = {}, - model_defaults, - related_attrs = {}; - - model_defaults = _.result(klass.prototype, 'defaults'); + default_vals = _.result(klass.prototype, 'defaults') || {}; if(schema){ - schema_defaults = _.object( - _(schema).keys(), - _(schema).chain() - .values() - .pluck('default') - .value() - ); + default_vals = _(default_vals).clone(); + + _(schema).each(function(attr, key){ + if(_(attr).has('default') && default_vals[key] === undefined) { + default_vals[key] = attr.default; + } + }); _(schema).each(function(attr, key){ var name; - if(attr.type == 'related' && attr._constructor){ + if(attr.type == 'related' && attr._constructor && !(key in default_vals)){ if(name = get_factory_name(attr._constructor)){ - related_attrs[key] = BackboneFactory.create(name); + default_vals[key] = BackboneFactory.create(name); }else if(name = get_collection_name(attr._constructor)){ - related_attrs[key] = BackboneFactory.create_collection(name); + default_vals[key] = BackboneFactory.create_collection(name); }else{ - related_attrs[key] = new attr._constructor(); + default_vals[key] = new attr._constructor(); } } }); @@ -74,9 +70,7 @@ var attributes = _.extend( { id: BackboneFactory.next("_" + factory_name + "_id") }, - schema_defaults, - related_attrs, - model_defaults, + default_vals, defaults.call(), attrs_generator.call() ); diff --git a/public/javascripts/test-setup.js b/public/javascripts/test-setup.js index ed7e9e1..c01041c 100644 --- a/public/javascripts/test-setup.js +++ b/public/javascripts/test-setup.js @@ -43,7 +43,7 @@ var Comment = Backbone.Model.extend({ }, author: { type: 'related', - related_to: User + _constructor: User } } diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index 0e372e4..f3d53c6 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -1,6 +1,14 @@ /*global sinon, describe, beforeEach, afterEach, it, expect, BackboneFactory, User, UserWithSchema, Post, PostWithSchema, Comments */ describe("Backbone Factory", function() { + beforeEach(function() { + this.addMatchers({ + toBeInstanceOf: function(expected) { + return this.actual instanceof expected; + } + }); + }); + describe("Defining and using Sequences", function(){ beforeEach(function() { @@ -42,8 +50,8 @@ describe("Backbone Factory", function() { it("return an instance of the Backbone Object requested", function() { - expect(this.postObject instanceof Post).toBeTruthy(); - expect(this.userObject instanceof User).toBeTruthy(); + expect(this.postObject).toBeInstanceOf(Post); + expect(this.userObject).toBeInstanceOf(User); }); // Not sure if this test is needed. But what the hell! @@ -64,7 +72,7 @@ describe("Backbone Factory", function() { }); it("should work if other factories are passed", function(){ - expect(this.postObject.get('author') instanceof User).toBeTruthy(); + expect(this.postObject.get('author')).toBeInstanceOf(User); }); it("should override defaults if arguments are passed on creation", function(){ @@ -153,32 +161,33 @@ describe("Backbone Factory", function() { describe("Related Model", function(){ it("should be created from schema if exists", function() { var post = BackboneFactory.create('post_with_schema'); - expect(post.get('author') instanceof UserWithSchema).toBeTruthy(); + expect(post.get('author')).toBeInstanceOf(UserWithSchema); }); it("should be created from schema even the related model has no schema", function() { var post = BackboneFactory.create('post_with_schema'); - expect(post.get('author_without_schema') instanceof User).toBeTruthy(); + expect(post.get('author_without_schema')).toBeInstanceOf(User); }); it("should work even when there are multiple factories for the same constructor", function(){ BackboneFactory.define('another_user_with_schema', UserWithSchema); var post = BackboneFactory.create('post_with_schema'); - expect(post.get('author') instanceof UserWithSchema).toBeTruthy(); + expect(post.get('author')).toBeInstanceOf(UserWithSchema); }); it("should be created even if there is no factory", function() { - var CommentCopy = Comment; - CommentCopy.prototype.schema = _.extend(Comment.prototype.schema, { - author: { - type: 'related', - _constructor: Backbone.Model - } + var CommentCopy = Comment.extend({ + schema: _.extend({}, Comment.prototype.schema, { + author: { + type: 'related', + _constructor: Backbone.Model + } + }) }); - BackboneFactory.define('comment', CommentCopy); - var comment = BackboneFactory.create('comment'); - expect(comment.get('author') instanceof Backbone.Model).toBeTruthy(); - expect(comment.get('author') instanceof User).toBeFalsy(); + BackboneFactory.define('comment_copy', CommentCopy); + var comment = BackboneFactory.create('comment_copy'); + expect(comment.get('author')).toBeInstanceOf(Backbone.Model); + expect(comment.get('author')).not.toBeInstanceOf(User); }); }); @@ -187,7 +196,7 @@ describe("Backbone Factory", function() { it("should be created from schema", function() { var post = BackboneFactory.create('post_with_schema'); - expect(post.get('comments') instanceof Comments).toBeTruthy(); + expect(post.get('comments')).toBeInstanceOf(Comments); }); it("should be of default size if size not given", function() { @@ -232,8 +241,8 @@ describe("Backbone Factory", function() { }); BackboneFactory.define('post', PostCopy); var post = BackboneFactory.create('post'); - expect(post.get('comments') instanceof Backbone.Collection).toBeTruthy(); - expect(post.get('comments') instanceof Comments).toBeFalsy(); + expect(post.get('comments')).toBeInstanceOf(Backbone.Collection); + expect(post.get('comments')).not.toBeInstanceOf(Comments); }); }); From b3fb9c55bdbbdaf321b16ab8e9cc3d48f64a6d54 Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Mon, 30 Sep 2013 18:51:03 +0530 Subject: [PATCH 17/18] adding a test case for create_collection --- spec/javascripts/BackboneFactorySpec.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/spec/javascripts/BackboneFactorySpec.js b/spec/javascripts/BackboneFactorySpec.js index f3d53c6..8c43c50 100644 --- a/spec/javascripts/BackboneFactorySpec.js +++ b/spec/javascripts/BackboneFactorySpec.js @@ -94,6 +94,19 @@ describe("Backbone Factory", function() { expect(secondID).toBe(firstID + 1); }); + + describe("create collection", function() { + + it("should create models with back-reference to collection", function() { + BackboneFactory.define('comment', Comment); + BackboneFactory.define_collection('comments', Comments, 2); + var collection = BackboneFactory.create_collection('comments'); + expect(collection.at(0).collection).toBe(collection); + }); + + }); + + describe("Error Messages", function() { it("should throw an error if factory_name is not proper", function() { From f44f487ff8c34da537b74f6f2f068aa0d80a93e9 Mon Sep 17 00:00:00 2001 From: Vignesh Nandha Kumar Date: Fri, 25 Oct 2013 22:46:05 +0530 Subject: [PATCH 18/18] Fixing few mistakes in README --- README.mkd | 42 +++++++++++++------------- public/javascripts/backbone-factory.js | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.mkd b/README.mkd index 3233304..bc79964 100644 --- a/README.mkd +++ b/README.mkd @@ -16,7 +16,7 @@ To use it, just [download](https://github.com/recruiterbox/Backbone-Factory/raw/ Usage ----- -Lets say you have two Backbone models, Post and User +Let's say you have two Backbone models - Post and User ```javascript var User = Backbone.Model.extend({ @@ -62,8 +62,8 @@ var userObject = BackboneFactory.create('user', function(){ return { name: "Custom Name", email: "custom@email.com" - }; - }); + }; +}); ``` ### Defining and using Collections @@ -79,10 +79,10 @@ var Users = Backbone.Collection.extend({ }); BackboneFactory.define_collection('posts', Posts, 3); //Third arugement is the default size of the collection -BackboneFactory.define_collection('users', Users, 4); +BackboneFactory.define_collection('users', Users, 4); -var postsCollection = BackboneFactory.create('posts'); //Creates 3 posts -var usersCollection = BackboneFactory.create('users',2) //Creates only 2 users overriding the default of 4 +var postsCollection = BackboneFactory.create_collection('posts'); //Creates 3 posts +var usersCollection = BackboneFactory.create_collection('users',2) //Creates only 2 users overriding the default of 4 ``` @@ -106,7 +106,7 @@ var PostWithSchema = Backbone.Model.extend({ }, author: { type: 'related', - constructor: User + _constructor: User } } @@ -124,7 +124,7 @@ var author = post.get('author'); console.log(author.get('name'); //Raghu ``` -Cool! isn't it? If defaults and schema are both present, default values from the backbone model take precedence over the scheme defaults. +Cool! isn't it? If defaults and schema are both present, default values from the backbone model take precedence over the schema defaults. Now, lets complicate this a bit further. ```javascript @@ -156,11 +156,11 @@ var PostWithSchema = Backbone.Model.extend({ }, author: { type: 'related', - constructor: User + _constructor: User } comments: { type: 'related', - constructor: Comments + _constructor: Comments } } }); @@ -171,15 +171,16 @@ BackboneFactory.define('comments', Comments, 2); var post = BackboneFactory.create('post_with_schema'); var comments = post.get('comments'); -console.log(comments.size()) //gives a value of 2 +console.log(comments.length) //gives a value of 2 ``` Its very easy to change the size of the collection of comments ```javascript var post = BackboneFactory.create('post_with_schema', function(){ - return { comments: BackboneFactory.create_collection('comments', 4) }); + return { comments: BackboneFactory.create_collection('comments', 4) }; +}); var comments = post.get('comments'); -console.log(comments.size()) //gives a value of 4 +console.log(comments.length) //gives a value of 4 ``` If a comments BackboneFactory is not defined, an empty collection of comments is created when a post is created. @@ -188,8 +189,8 @@ If a comments BackboneFactory is not defined, an empty collection of comments is Often, we'd like to generate unique values for model attributes when new objects are created. For example, we may want the username/email of a user to be always unique. We can use sequences for this. ```javascript BackboneFactory.define_sequence('email', function(n){ - return "person"+n+"@example.com"; - }); + return "person"+n+"@example.com"; +}); var email = BackboneFactory.next('email') // person1@example.com ``` @@ -198,12 +199,11 @@ var email = BackboneFactory.next('email') // person1@example.com ```javascript BackboneFactory.define('user', User, function(){ - return { - name : 'Backbone User', - email: BackboneFactory.next('email') - }; - } - ); + return { + name : 'Backbone User', + email: BackboneFactory.next('email') + }; +}); var user = BackboneFactory.create('user); console.log(user.get('email') // person2@example.com ``` diff --git a/public/javascripts/backbone-factory.js b/public/javascripts/backbone-factory.js index 05cc20f..13c0ad3 100644 --- a/public/javascripts/backbone-factory.js +++ b/public/javascripts/backbone-factory.js @@ -1,7 +1,7 @@ /*global BackboneFactory */ // Backbone Factory JS -// https://github.com/SupportBee/Backbone-Factory +// https://github.com/Aplopio/Backbone-Factory (function(){