Commits

Gary Chambers committed 7eb6e8b

Moved MVC to App namespace

MVC did not properly encapsulate the behaviour of the module

Comments (0)

Files changed (12)

src/addons/app/engine.js

+/**
+App storage engine factory.
+
+@class Engine
+@static
+@category addons app
+**/
+Jazz.NS.set("App.Engine", (function( window, document, undefined )
+{
+	var Engine,
+
+		data,
+		config;
+
+	Engine = {};
+
+	config = {
+		engine: Jazz.Storage
+	};
+
+	/**
+	Return a storage instance
+	for the specified model
+
+	@method load
+	@param {String} modelName
+	@return {Object}
+	**/
+	Engine.load = function load( modelName )
+	{
+		var storage;
+
+		if( data === undefined )
+		{
+			data = Jazz.Storage.load("App:data");
+		}
+
+		storage = data.get( modelName );
+
+		if( !storage )
+		{
+			storage = data.set(
+				modelName,
+				config.engine.load("App:data:" + modelName.toLowerCase())
+			);
+		}
+
+		return storage;
+	};
+
+	/**
+	Sets a custom storage engine.
+
+	@method use
+	@param {Function} engine Storage engine constructor
+	@return {Undefined}
+	**/
+	Engine.use = function use( engine )
+	{
+		config.engine = engine;
+	};
+
+	return Engine;
+})( this, this.document ));

src/addons/app/manager.js

+/**
+Base data manager class. Extend this class
+for custom object retrieval behaviour.
+
+@class Manager
+@constructor
+@category addons app
+**/
+Jazz.NS.set("App.Manager", (function( global, undefined )
+{
+	var Manager;
+	
+	Manager = Jazz.Class.create({
+		
+		init: function( model )
+		{
+			this.model = model;
+		},
+
+		/**
+		Returns an instance of
+		Jazz.App.QuerySet, bound
+		to the current model.
+
+		@method getQuerySet
+		@return {Object}
+		**/
+		getQuerySet: function getQuerySet()
+		{
+			return new Jazz.App.QuerySet( this.model );
+		},
+
+		/**
+		Returns complete queryset for
+		the attached model.
+
+		@method all
+		@return {Object}
+		**/
+		all: function all()
+		{
+			return this.getQuerySet().all();
+		},
+
+		/**
+		Returns the number of items in
+		the queryset.
+
+		@method count
+		@return {Number}
+		**/
+		count: function count()
+		{
+			return this.getQuerySet().count();
+		},
+
+		/**
+		Empties the data collection for
+		the current model.
+
+		@method empty
+		@return {Undefined}
+		**/
+		empty: function empty()
+		{
+			var data;
+			data = this.model.getData();
+
+			Jazz.Iter.forEach(data.keys(), function( key )
+			{
+				data.unset( key );
+			});
+		},
+
+		/**
+		Returns a queryset filtered
+		by the specified comparator.
+
+		@method filter
+		@param {Function} comparator
+		@return {Object}
+		**/
+		filter: function filter( comparator )
+		{
+			return this.getQuerySet().filter( comparator );
+		},
+
+		/**
+		Get a single instance
+		from the data collection.
+
+		@method get
+		@param {Object} where The match criteria
+		@return {Object}
+		**/
+		get: function get( where )
+		{
+			return this.getQuerySet().get( where );
+		}
+
+	});
+
+	return Manager;
+})( this ));

src/addons/app/model.js

+/**
+@class Model
+@constructor
+@param {Object} data
+@category addons app
+**/
+Jazz.NS.set("App.Model", (function( global, undefined )
+{
+	var Model,
+
+		_data,
+		_models;
+
+	_models = Jazz.Storage.load("App:models");
+
+	Model = Jazz.Class.create(Jazz.Storage, {
+
+		init: function( data )
+		{
+			// In order to correctly reference
+			// the model metadata, we require
+			// models to be constructed via
+			// a factory method.
+
+			if( !Jazz.Obj.has(this, "_meta") )
+			{
+				throw {
+					name: "ReferenceError",
+					message: "Models must be defined via Jazz.App.Model.create"
+				};
+			}
+
+			this.values = Jazz.Obj.extend({}, data);
+		},
+
+		/**
+		Save the current model instance.
+
+		@method save
+		@return {Undefined}
+		**/
+		save: function save()
+		{
+			Jazz.App.Engine.load(this._meta.name)
+				.set(this.getID(), this.values);
+		},
+
+		/**
+		Get the primary key id for
+		this resource.
+
+		@method getID
+		@return {Mixed}
+		**/
+		getID: function getID()
+		{
+			var id;
+			id = this.get("id", this.get("_uuid"));
+
+			if(!id)
+			{
+				id = this.set( "_uuid", Jazz.Util.UUID() );
+			}
+
+			return id;
+		},
+
+		/**
+		Creates a permalink URL for the
+		current resource. Overload this
+		method for custom URLs.
+
+		@method getURL
+		@return {String}
+		**/
+		getURL: function getURL()
+		{
+			return "/" + this._meta.name.toLowerCase() + "/" + this.getID();
+		}
+	
+	});
+
+	Jazz.Obj.extend(Model, {
+
+		/**
+		@method create
+		@static
+		@param {String} name
+		@param {Object} methods
+		@return {Function}
+		**/
+		create: function create( name, methods )
+		{
+			var klass,
+				_init;
+
+			// Wrap new model constructor to ensure
+			// that base class constructor is called
+			// first.
+
+			_init = methods.init || Jazz.Util.noop;
+			methods.init = function init( data )
+			{
+				this._meta = {
+					"name": name,
+					"localMethods": Jazz.Obj.keys( methods )
+				};
+
+				this._super("init", data);
+				_init( data );
+			};
+
+			klass = Jazz.Class.create(Jazz.App.Model, methods);
+
+			_models.set(name, klass);
+
+			klass.objects = new Jazz.App.Manager( klass );
+			klass.getData = function getData()
+			{
+				return Jazz.App.Engine.load(name);
+			};
+
+			return klass;
+		},
+
+		/**
+		Create an instance of the
+		model identified by `name`
+
+		@method init
+		@static
+		@param {String} name Model name
+		@return {Object} An instance of Jazz.App.Model
+		**/
+		init: function init( name, values )
+		{
+			var Constructor;
+			Constructor = _models.get(name);
+			return new Constructor( values );
+		}
+
+	});
+
+	return Model;
+
+})( this ));

src/addons/app/queryset.js

+/**
+@class QuerySet
+@constructor
+@param {Object} model An instance of Jazz.App.Model
+@category addons app
+**/
+Jazz.NS.set("App.QuerySet", (function( global, undefined )
+{
+	var QuerySet;
+
+	QuerySet = Jazz.Class.create({
+
+		init: function( model )
+		{
+			this.model = model;
+
+			this.options = {
+				filterBy: [],
+				sortBy: []
+			};
+		},
+
+		/**
+		Returns the number of items
+		in the queryset.
+
+		@method count
+		@return {Number}
+		**/
+		count: function count()
+		{
+			var len,
+				_sortBy;
+
+			// Sorting has no effect on
+			// queryset length, so
+			// bypass for length iteration
+
+			_sortBy = this.options.sortBy;
+			this.options.sortBy = [];
+
+			len = this.fetch().length;
+
+			this.options.sortBy = _sortBy;
+
+			return len;
+		},
+
+		/**
+		Evaluate the queryset instance
+		and return the results.
+
+		@method fetch
+		@private
+		@return {Array}
+		**/
+		fetch: function fetch()
+		{
+			var output,
+				self;
+
+			output = [];
+			self = this;
+
+			Jazz.Iter.forEach(this.model.getData().all(), function(item, id)
+			{
+				var test;
+				test = true;
+
+				Jazz.Iter.forEach(self.options.filterBy, function(fn)
+				{
+					item = new self.model(item);
+
+					if( !fn(item) )
+					{
+						test = false;
+						Jazz.Iter.breakLoop();
+					}
+				});
+
+				if( test )
+				{
+					output.push( item );
+				}
+			});
+
+			Jazz.Iter.forEach(this.options.sortBy, function(fn)
+			{
+				output.sort(fn);
+			});
+
+			return output;
+		},
+
+		/**
+		Return all stored data objects.
+
+		@method all
+		@chainable
+		**/
+		all: function all()
+		{
+			this.options.filterBy = [];
+			return this;
+		},
+
+		/**
+		Add a new filter condition
+		to the queryset.
+
+		@method filter
+		@param {Function} comparator The comparator function
+		@chainable
+		**/
+		filter: function filter( comparator )
+		{
+			this.options.filterBy.push( comparator );
+			return this;
+		},
+
+		/**
+		Add sorting method to queryset.
+
+		Each comparator function accepts
+		two arguments: the nth and (n+1)th
+		items in the collection.
+
+		Return -1 to keep to preserve the
+		current order and return 1 to invert.
+
+		@method sort
+		@param {Function} fn
+		@chainable
+		**/
+		sort: function sort( fn )
+		{
+			this.options.sortBy.push( fn );
+			return this;
+		}
+
+	});
+
+	return QuerySet;
+})( this ));	

src/addons/app/view.js

+/**
+A syntactic wrapper around the Template module.
+This is designed for use within the Router module
+in a View-Controller relationship.
+
+@class View
+@constructor
+@category addon app
+
+@param {Mixed} elem The target element or selector string
+@param {String} path The template path
+@param {Object} context The context to be passed to the compiled template
+@return {Undefined}
+**/
+Jazz.NS.set("View", function View( elem, path, context )
+{
+	"use strict";
+
+	var template;
+
+	elem = Jazz.Obj.isType( elem, "String" ) ?
+		Jazz.DOM.query( elem ) : elem;
+
+	template = new Jazz.Template( path );
+	template.bind( elem );
+	template.context( context );
+});

src/addons/mvc/engine.js

-/**
-MVC storage engine factory.
-
-@class Engine
-@static
-@category addons
-**/
-Jazz.NS.set("MVC.Engine", (function( window, document, undefined )
-{
-	var Engine,
-
-		data,
-		config;
-
-	Engine = {};
-
-	config = {
-		engine: Jazz.Storage
-	};
-
-	/**
-	Return a storage instance
-	for the specified model
-
-	@method load
-	@param {String} modelName
-	@return {Object}
-	**/
-	Engine.load = function load( modelName )
-	{
-		var storage;
-
-		if( data === undefined )
-		{
-			data = Jazz.Storage.load("mvc:data");
-		}
-
-		storage = data.get( modelName );
-
-		if( !storage )
-		{
-			storage = data.set(
-				modelName,
-				config.engine.load("mvc:data:" + modelName.toLowerCase())
-			);
-		}
-
-		return storage;
-	};
-
-	/**
-	Sets a custom storage engine.
-
-	@method use
-	@param {Function} engine Storage engine constructor
-	@return {Undefined}
-	**/
-	Engine.use = function use( engine )
-	{
-		config.engine = engine;
-	};
-
-	return Engine;
-})( this, this.document ));

src/addons/mvc/manager.js

-/**
-Base data manager class. Extend this class
-for custom object retrieval behaviour.
-
-@class Manager
-@constructor
-@category addons
-**/
-Jazz.NS.set("MVC.Manager", (function( window, document, undefined )
-{
-	var Manager;
-	
-	Manager = Jazz.Class.create({
-		
-		init: function( model )
-		{
-			this.model = model;
-		},
-
-		/**
-		Returns an instance of
-		Jazz.MVC.QuerySet, bound
-		to the current model.
-
-		@method getQuerySet
-		@return {Object}
-		**/
-		getQuerySet: function getQuerySet()
-		{
-			return new Jazz.MVC.QuerySet( this.model );
-		},
-
-		/**
-		Returns complete queryset for
-		the attached model.
-
-		@method all
-		@return {Object}
-		**/
-		all: function all()
-		{
-			return this.getQuerySet().all();
-		},
-
-		/**
-		Returns the number of items in
-		the queryset.
-
-		@method count
-		@return {Number}
-		**/
-		count: function count()
-		{
-			return this.getQuerySet().count();
-		},
-
-		/**
-		Empties the data collection for
-		the current model.
-
-		@method empty
-		@return {Undefined}
-		**/
-		empty: function empty()
-		{
-			var data;
-			data = this.model.getData();
-
-			Jazz.Iter.forEach(data.keys(), function( key )
-			{
-				data.unset( key );
-			});
-		},
-
-		/**
-		Returns a queryset filtered
-		by the specified comparator.
-
-		@method filter
-		@param {Function} comparator
-		@return {Object}
-		**/
-		filter: function filter( comparator )
-		{
-			return this.getQuerySet().filter( comparator );
-		},
-
-		/**
-		Get a single instance
-		from the data collection.
-
-		@method get
-		@param {Object} where The match criteria
-		@return {Object}
-		**/
-		get: function get( where )
-		{
-			return this.getQuerySet().get( where );
-		}
-
-	});
-
-	return Manager;
-})( this, this.document ));

src/addons/mvc/model.js

-/**
-@class Model
-@constructor
-@param {Object} data
-@category addons
-**/
-Jazz.NS.set("MVC.Model", (function( window, document, undefined )
-{
-	var Model,
-
-		_data,
-		_models;
-
-	_models = Jazz.Storage.load("mvc:models");
-
-	Model = Jazz.Class.create(Jazz.Storage, {
-
-		init: function( data )
-		{
-			// In order to correctly reference
-			// the model metadata, we require
-			// models to be constructed via
-			// a factory method.
-
-			if( !Jazz.Obj.has(this, "_meta") )
-			{
-				throw {
-					name: "ReferenceError",
-					message: "Models must be defined via Jazz.MVC.Model.create"
-				};
-			}
-
-			this.values = Jazz.Obj.extend({}, data);
-		},
-
-		/**
-		Save the current model instance.
-
-		@method save
-		@return {Undefined}
-		**/
-		save: function save()
-		{
-			Jazz.MVC.Engine.load(this._meta.name)
-				.set(this.getID(), this.values);
-		},
-
-		/**
-		Get the primary key id for
-		this resource.
-
-		@method getID
-		@return {Mixed}
-		**/
-		getID: function getID()
-		{
-			var id;
-			id = this.get("id", this.get("_uuid"));
-
-			if(!id)
-			{
-				id = this.set( "_uuid", Jazz.Util.UUID() );
-			}
-
-			return id;
-		},
-
-		/**
-		Creates a permalink URL for the
-		current resource. Overload this
-		method for custom URLs.
-
-		@method getURL
-		@return {String}
-		**/
-		getURL: function getURL()
-		{
-			return "/" + this._meta.name.toLowerCase() + "/" + this.getID();
-		}
-	
-	});
-
-	Jazz.Obj.extend(Model, {
-
-		/**
-		@method create
-		@static
-		@param {String} name
-		@param {Object} methods
-		@return {Function}
-		**/
-		create: function create( name, methods )
-		{
-			var klass,
-				_init;
-
-			// Wrap new model constructor to ensure
-			// that base class constructor is called
-			// first.
-
-			_init = methods.init || Jazz.Util.noop;
-			methods.init = function init( data )
-			{
-				this._meta = {
-					"name": name,
-					"localMethods": Jazz.Obj.keys( methods )
-				};
-
-				this._super("init", data);
-				_init( data );
-			};
-
-			klass = Jazz.Class.create(Jazz.MVC.Model, methods);
-
-			_models.set(name, klass);
-
-			klass.objects = new Jazz.MVC.Manager( klass );
-			klass.getData = function getData()
-			{
-				return Jazz.MVC.Engine.load(name);
-			};
-
-			return klass;
-		},
-
-		/**
-		Create an instance of the
-		model identified by `name`
-
-		@method init
-		@static
-		@param {String} name Model name
-		@return {Object} An instance of Jazz.MVC.Model
-		**/
-		init: function init( name, values )
-		{
-			var Constructor;
-			Constructor = _models.get(name);
-			return new Constructor( values );
-		}
-
-	});
-
-	return Model;
-
-})( this, this.document ));

src/addons/mvc/queryset.js

-/**
-@class QuerySet
-@constructor
-@param {Object} model An instance of Jazz.MVC.Model
-@category addons
-**/
-Jazz.NS.set("MVC.QuerySet", (function( window, document, undefined )
-{
-	var QuerySet;
-
-	QuerySet = Jazz.Class.create({
-
-		init: function( model )
-		{
-			this.model = model;
-
-			this.options = {
-				filterBy: [],
-				sortBy: []
-			};
-		},
-
-		/**
-		Returns the number of items
-		in the queryset.
-
-		@method count
-		@return {Number}
-		**/
-		count: function count()
-		{
-			var len,
-				_sortBy;
-
-			// Sorting has no effect on
-			// queryset length, so
-			// bypass for length iteration
-
-			_sortBy = this.options.sortBy;
-			this.options.sortBy = [];
-
-			len = this.fetch().length;
-
-			this.options.sortBy = _sortBy;
-
-			return len;
-		},
-
-		/**
-		Evaluate the queryset instance
-		and return the results.
-
-		@method fetch
-		@private
-		@return {Array}
-		**/
-		fetch: function fetch()
-		{
-			var output,
-				self;
-
-			output = [];
-			self = this;
-
-			Jazz.Iter.forEach(this.model.getData().all(), function(item, id)
-			{
-				var test;
-				test = true;
-
-				Jazz.Iter.forEach(self.options.filterBy, function(fn)
-				{
-					item = new self.model(item);
-
-					if( !fn(item) )
-					{
-						test = false;
-						Jazz.Iter.breakLoop();
-					}
-				});
-
-				if( test )
-				{
-					output.push( item );
-				}
-			});
-
-			Jazz.Iter.forEach(this.options.sortBy, function(fn)
-			{
-				output.sort(fn);
-			});
-
-			return output;
-		},
-
-		/**
-		Return all stored data objects.
-
-		@method all
-		@chainable
-		**/
-		all: function all()
-		{
-			this.options.filterBy = [];
-			return this;
-		},
-
-		/**
-		Add a new filter condition
-		to the queryset.
-
-		@method filter
-		@param {Function} comparator The comparator function
-		@chainable
-		**/
-		filter: function filter( comparator )
-		{
-			this.options.filterBy.push( comparator );
-			return this;
-		},
-
-		/**
-		Add sorting method to queryset.
-
-		Each comparator function accepts
-		two arguments: the nth and (n+1)th
-		items in the collection.
-
-		Return -1 to keep to preserve the
-		current order and return 1 to invert.
-
-		@method sort
-		@param {Function} fn
-		@chainable
-		**/
-		sort: function sort( fn )
-		{
-			this.options.sortBy.push( fn );
-			return this;
-		}
-
-	});
-
-	return QuerySet;
-})( this, this.document ));	

src/addons/mvc/view.js

-/**
-A syntactic wrapper around the Template module.
-This is designed for use within the Router module
-in a View-Controller relationship.
-
-@class View
-@constructor
-@category addon
-
-@param {Mixed} elem The target element or selector string
-@param {String} path The template path
-@param {Object} context The context to be passed to the compiled template
-@return {Undefined}
-**/
-Jazz.NS.set("View", function View( elem, path, context )
-{
-	"use strict";
-
-	var template;
-
-	elem = Jazz.Obj.isType( elem, "String" ) ?
-		Jazz.DOM.query( elem ) : elem;
-
-	template = new Jazz.Template( path );
-	template.bind( elem );
-	template.context( context );
-});

tests/addons/app.js

+(function( window, document, undefined )
+{
+
+	var obj;
+
+	module("Addons/App");
+
+	baseTests(
+		"Jazz.App",
+		Jazz.App,
+		"Model Manager QuerySet".split(" ")
+	);
+
+	test("Jazz.App.Model", function()
+	{
+		var Person,
+			people,
+			p;
+
+		Person = Jazz.App.Model.create("Person", {
+			getFullName: function()
+			{
+				return this.get("firstName") + " " + this.get("lastName");
+			}
+		});
+
+		var i = 10000;
+
+		while(i--)
+		{
+			p = Jazz.App.Model.init("Person", {
+				firstName: "John",
+				lastName: "Smith"
+			});
+
+			p.save();
+		}
+
+		// Object instance operations
+		equal( p.getFullName(), "John Smith", "Model instance correctly inherits model prototype" );
+		notEqual( p.getID(), undefined, "Model instance has been assigned an ID" );
+		equal( p.getURL(), "/person/" + p.getID(), "Model instance correctly reports resource URL" );
+
+		// QuerySet operations
+		equal( Person.objects.count(), 10000, "QuerySet reports correct number of items (10000)" );
+
+		Person.objects.empty();
+		equal( Person.objects.count(), 0, "QuerySet reports correct number of items (0)" );
+
+		Jazz.Iter.forEach(
+			["Richard Nixon", "Barack Obama", "George Bush", "George Washington"],
+			function( name )
+			{
+				name = name.split(" ");
+				new Person({
+					firstName: name[0],
+					lastName: name[1]
+				}).save();
+			}
+		);
+
+		equal( Person.objects.count(), 4, "QuerySet reports correct number of items (4)" );
+
+		people = Person.objects.filter(function(p)
+		{
+			return p.get("firstName") === "George";
+		});
+
+		equal( people.count(), 2, "QuerySet#filter reduces the queryset to the correct number of elements" );
+	});
+
+})( this, this.document );
 		<script src="../src/addons/template.js"></script>
 		<script src="../src/addons/router.js"></script>
 
-		<script src="../src/addons/mvc/queryset.js"></script>
-		<script src="../src/addons/mvc/manager.js"></script>
-		<script src="../src/addons/mvc/engine.js"></script>
-		<script src="../src/addons/mvc/model.js"></script>
+		<script src="../src/addons/App/queryset.js"></script>
+		<script src="../src/addons/App/manager.js"></script>
+		<script src="../src/addons/App/engine.js"></script>
+		<script src="../src/addons/App/model.js"></script>
 		<!-- #END Jazz.JS Source -->
 
 		<!-- #BEGIN Unit Tests -->
 		<script src="core/storage.js"></script>
 		<script src="core/event.js"></script>
 
-		<script src="addons/mvc.js"></script>
+		<script src="addons/App.js"></script>
 		<!-- #END Unit Tests -->
 	</body>
 </html>