diff --git a/test_app/spec/javascripts/controller_builder_spec.js b/test_app/spec/javascripts/controller_builder_spec.js index 7b3bfbb..2505e8a 100644 --- a/test_app/spec/javascripts/controller_builder_spec.js +++ b/test_app/spec/javascripts/controller_builder_spec.js @@ -1,104 +1,49 @@ describe('Paloma.ControllerBuilder', function(){ - var _builder = null; - function builder(){ return _builder; } - - function newBuilder(){ - _builder = new Paloma.ControllerBuilder(); - return _builder; - } + var TestController = Paloma.controller('Test'); + describe('#build(options)', function(){ - describe('#build(controllerAndParent, prototype)', function(){ - describe('when controller is not yet existing', function(){ - it('creates a new controller', function(){ - var controller = newBuilder().build('MyController'), - instance = new controller(); + describe('when options.controller has no match', function(){ + var factory = {get: function(controller){ return null; }}, + builder = new Paloma.ControllerBuilder(factory); - expect(instance instanceof Paloma.BaseController).toBeTruthy(); - }); - - describe('when prototype is present', function(){ - it('adds the prototype to the controller', function(){ - var controller = newBuilder().build('MyController', {a: 100}); - - expect(controller.prototype.a).toEqual(100); - }); - }); - - describe('when parent is present', function(){ - it('creates a subclass of that parent', function(){ - var parent = newBuilder().build('Parent'), - child = builder().build('Child < Parent'); - - var controller = new child(); - expect(controller instanceof parent).toBeTruthy(); - }); - }); - }); - - describe('when controller is already existing', function(){ - it('returns the existing controller', function(){ - var controller = newBuilder().build('test2'); - expect( builder().build('test2') ).toEqual(controller); - }); - - describe('when prototype is present', function(){ - var controller = newBuilder().build('Test', {number: 9}); - builder().build('Test', {number: 10}); - - it('updates the current prototype', function(){ - expect(controller.prototype.number).toEqual(10); - }); - }); - - describe('when parent is present', function(){ - var oldParent = newBuilder().build('OldParent'), - newParent = builder().build('NewParent'); - - describe('when no previous parent', function(){ - var child = builder().build('ChildA'); - builder().build('ChildA < NewParent'); - - var instance = new child(); - - it('assigns the new parent', function(){ - expect(instance instanceof newParent).toBeTruthy(); - }); - }); - - describe('when has previous parent', function(){ - var child = builder().build('ChildB < OldParent'); - builder().build('ChildB < NewParent'); - - var instance = new child(); - - it('updates removes the oldParent', function(){ - expect(instance instanceof oldParent).toBeFalsy(); - }); - - it('assigns the new parent', function(){ - expect(instance instanceof newParent).toBeTruthy(); - }); - }); - }); - }); - }); - - describe('#get(name)', function(){ - describe('when name has no match', function(){ it('returns null', function(){ - expect( newBuilder().get('unknown') ).toBeNull(); + var options = {controller: 'Test', action: 'show'}; + expect( builder.build(options) ).toBeNull(); }); }); - describe('when name has match', function(){ - it('returns the matched controller', function(){ - var controller = newBuilder().build('myController'); - expect( builder().get('myController') ).toEqual(controller); + describe('when options.controller has a match', function(){ + var factory = {get: function(controller){ return TestController; }}, + builder = new Paloma.ControllerBuilder(factory); + + var options = { + controller: 'Test', + action: 'show', + params: {a: 1, b: 2} + }; + + var controller = builder.build(options); + + it('returns a new instance of the controller class', function(){ + expect(controller instanceof TestController).toBeTruthy(); + }); + + it("initializes controller instance's params", function(){ + var expectedParams = {_controller: 'Test', _action: 'show', a: 1, b: 2}; + var correct = true; + + for (var k in expectedParams){ + if (controller.params[k] != expectedParams[k]) + correct = false; + } + + expect(correct).toBeTruthy(); }); }); + }); }); diff --git a/test_app/spec/javascripts/controller_class_factory_spec.js b/test_app/spec/javascripts/controller_class_factory_spec.js new file mode 100644 index 0000000..5c3dd56 --- /dev/null +++ b/test_app/spec/javascripts/controller_class_factory_spec.js @@ -0,0 +1,104 @@ +describe('Paloma.ControllerClassFactory', function(){ + + var _factory = null; + function factory(){ return _factory; } + + function newFactory(){ + _factory = new Paloma.ControllerClassFactory(); + return _factory; + } + + + + describe('#make(controllerAndParent, prototype)', function(){ + describe('when controller is not yet existing', function(){ + it('creates a new controller', function(){ + var controller = newFactory().make('MyController'), + instance = new controller(); + + expect(instance instanceof Paloma.BaseController).toBeTruthy(); + }); + + describe('when prototype is present', function(){ + it('adds the prototype to the controller', function(){ + var controller = newFactory().make('MyController', {a: 100}); + + expect(controller.prototype.a).toEqual(100); + }); + }); + + describe('when parent is present', function(){ + it('creates a subclass of that parent', function(){ + var parent = newFactory().make('Parent'), + child = factory().make('Child < Parent'); + + var controller = new child(); + expect(controller instanceof parent).toBeTruthy(); + }); + }); + }); + + describe('when controller is already existing', function(){ + it('returns the existing controller', function(){ + var controller = newFactory().make('test2'); + expect( factory().make('test2') ).toEqual(controller); + }); + + describe('when prototype is present', function(){ + var controller = newFactory().make('Test', {number: 9}); + factory().make('Test', {number: 10}); + + it('updates the current prototype', function(){ + expect(controller.prototype.number).toEqual(10); + }); + }); + + describe('when parent is present', function(){ + var oldParent = newFactory().make('OldParent'), + newParent = factory().make('NewParent'); + + describe('when no previous parent', function(){ + var child = factory().make('ChildA'); + factory().make('ChildA < NewParent'); + + var instance = new child(); + + it('assigns the new parent', function(){ + expect(instance instanceof newParent).toBeTruthy(); + }); + }); + + describe('when has previous parent', function(){ + var child = factory().make('ChildB < OldParent'); + factory().make('ChildB < NewParent'); + + var instance = new child(); + + it('updates removes the oldParent', function(){ + expect(instance instanceof oldParent).toBeFalsy(); + }); + + it('assigns the new parent', function(){ + expect(instance instanceof newParent).toBeTruthy(); + }); + }); + }); + }); + }); + + describe('#get(name)', function(){ + describe('when name has no match', function(){ + it('returns null', function(){ + expect( newFactory().get('unknown') ).toBeNull(); + }); + }); + + describe('when name has match', function(){ + it('returns the matched controller', function(){ + var controller = newFactory().make('myController'); + expect( factory().get('myController') ).toEqual(controller); + }); + }); + }); + +}); diff --git a/vendor/assets/javascripts/paloma/controller_builder.js b/vendor/assets/javascripts/paloma/controller_builder.js index 51a0dc4..f46ca93 100644 --- a/vendor/assets/javascripts/paloma/controller_builder.js +++ b/vendor/assets/javascripts/paloma/controller_builder.js @@ -1,61 +1,34 @@ -Paloma.ControllerBuilder = function(){ - this._controllers = {}; - this._inheritanceSymbol = '<'; +Paloma.ControllerBuilder = function(classFactory){ + this.classFactory = classFactory; + this.options = {}; }; Paloma.ControllerBuilder.prototype = { - build: function(controllerAndParent, prototype){ - var parts = this._extractParts(controllerAndParent), - controller = this._getOrCreate( parts.controller ); + build: function(options){ + this.options = options; - this._updatePrototype(controller, prototype); - this._updateParent(controller, parts.parent); + var ControllerClass = this._controllerClass(); + if ( !ControllerClass ) return null; - return controller; + return new ControllerClass( this._buildParams() ); }, - get: function(name){ - return this._controllers[name] || null; + _controllerClass: function(){ + return this.classFactory.get( this.options.controller ); }, - _updateParent: function(controller, parent){ - if (!parent) return; - - var parentClass = this.get(parent); - if (parentClass) controller.prototype.__proto__ = parentClass.prototype; - }, - - _updatePrototype: function(controller, newPrototype){ - for (var k in newPrototype) - if (newPrototype.hasOwnProperty(k)) - controller.prototype[k] = newPrototype[k]; - }, - - _getOrCreate: function(name){ - return this.get(name) || this._create(name); - }, - - _create: function(name){ - var controller = function(params){ - Paloma.BaseController.call(this, params); + _buildParams: function(){ + var params = { + _controller: this.options.controller, + _action: this.options.action }; - controller.prototype.__proto__ = Paloma.BaseController.prototype; + for (var k in this.options.params) + if (this.options.params.hasOwnProperty(k)) + params[k] = this.options.params[k]; - this._controllers[name] = controller; - return controller; - }, - - _extractParts: function(controllerAndParent){ - var parts = controllerAndParent.split( this._inheritanceSymbol ); - - var controller = parts[0].trim(), - parent = parts[1]; - - if (parent) parent = parent.trim(); - - return {controller: controller, parent: parent}; + return params; } }; diff --git a/vendor/assets/javascripts/paloma/controller_class_factory.js b/vendor/assets/javascripts/paloma/controller_class_factory.js new file mode 100644 index 0000000..53417cc --- /dev/null +++ b/vendor/assets/javascripts/paloma/controller_class_factory.js @@ -0,0 +1,61 @@ +Paloma.ControllerClassFactory = function(){ + this._controllers = {}; + this._inheritanceSymbol = '<'; +}; + +Paloma.ControllerClassFactory.prototype = { + + make: function(controllerAndParent, prototype){ + var parts = this._extractParts(controllerAndParent), + controller = this._getOrCreate( parts.controller ); + + this._updatePrototype(controller, prototype); + this._updateParent(controller, parts.parent); + + return controller; + }, + + get: function(name){ + return this._controllers[name] || null; + }, + + _updateParent: function(controller, parent){ + if (!parent) return; + + var parentClass = this.get(parent); + if (parentClass) controller.prototype.__proto__ = parentClass.prototype; + }, + + _updatePrototype: function(controller, newPrototype){ + for (var k in newPrototype) + if (newPrototype.hasOwnProperty(k)) + controller.prototype[k] = newPrototype[k]; + }, + + _getOrCreate: function(name){ + return this.get(name) || this._create(name); + }, + + _create: function(name){ + var controller = function(params){ + Paloma.BaseController.call(this, params); + }; + + controller.prototype.__proto__ = Paloma.BaseController.prototype; + + this._controllers[name] = controller; + return controller; + }, + + _extractParts: function(controllerAndParent){ + var parts = controllerAndParent.split( this._inheritanceSymbol ); + + var controller = parts[0].trim(), + parent = parts[1]; + + if (parent) parent = parent.trim(); + + return {controller: controller, parent: parent}; + } + +}; diff --git a/vendor/assets/javascripts/paloma/engine.js b/vendor/assets/javascripts/paloma/engine.js index 34c55f5..84f32e3 100644 --- a/vendor/assets/javascripts/paloma/engine.js +++ b/vendor/assets/javascripts/paloma/engine.js @@ -1,5 +1,5 @@ -Paloma.Engine = function(config){ - this.builder = config.builder; +Paloma.Engine = function(controllerBuilder){ + this.controllerBuilder = controllerBuilder; this._clearRequest(); }; @@ -29,27 +29,29 @@ Paloma.Engine.prototype = { this._logRequest(); this._lastRequest = this._request; - var controllerClass = this.builder.get( this._request.controller ); - - if (controllerClass){ - var controller = new controllerClass( this._request.params ); - this._executeActionOf(controller); - } - + this._executeControllerAction(); this._clearRequest(); }, - _executeActionOf: function(controller){ - var action = controller[ this._request.action ]; + _executeControllerAction: function(){ + var controller = this._buildController(); + if (!controller) return; - if (action){ - var callbackPerformer = new Paloma.BeforeCallbackPerformer(controller); - callbackPerformer.perform( this._request.action ); + var callbackPerformer = new Paloma.BeforeCallbackPerformer(controller); + callbackPerformer.perform( this._request.action ); - action.call(controller); + var method = controller[ this._request.action ]; + if (method) method.call(controller); - this._lastRequest.executed = true; - } + this._lastRequest.executed = true; + }, + + _buildController: function(){ + return this.controllerBuilder.build({ + controller: this._request.controller, + action: this._request.action, + params: this._request.params + }); }, _shouldStop: function(){ @@ -71,4 +73,5 @@ Paloma.Engine.prototype = { _clearRequest: function(){ this._request = null; } + }; diff --git a/vendor/assets/javascripts/paloma/index.js b/vendor/assets/javascripts/paloma/index.js index c080857..1b348ec 100644 --- a/vendor/assets/javascripts/paloma/index.js +++ b/vendor/assets/javascripts/paloma/index.js @@ -1,6 +1,7 @@ //= require ./init.js //= require ./base_controller.js -//= require ./controller_builder.js +//= require ./controller_class_factory.js //= require ./before_callback_performer.js +//= require ./controller_builder.js //= require ./engine.js //= require ./paloma.js diff --git a/vendor/assets/javascripts/paloma/paloma.js b/vendor/assets/javascripts/paloma/paloma.js index 6e12dc0..9fc381a 100644 --- a/vendor/assets/javascripts/paloma/paloma.js +++ b/vendor/assets/javascripts/paloma/paloma.js @@ -1,10 +1,15 @@ (function(Paloma){ - Paloma._controllerBuilder = new Paloma.ControllerBuilder(); - Paloma.engine = new Paloma.Engine({builder: Paloma._controllerBuilder}); + var classFactory = new Paloma.ControllerClassFactory(), + controllerBuilder = new Paloma.ControllerBuilder(classFactory), + engine = new Paloma.Engine(controllerBuilder) + + Paloma._controllerClassFactory = classFactory; + Paloma._controllerBuilder = controllerBuilder + Paloma.engine = engine; Paloma.controller = function(name, prototype){ - return Paloma._controllerBuilder.build(name, prototype); + return classFactory.make(name, prototype); }; Paloma._executeHook = function(){ @@ -13,12 +18,12 @@ }; Paloma.start = function(){ - if ( !this.engine.hasRequest() ) this._executeHook(); - if ( this.engine.hasRequest() ) this.engine.start(); + if ( !engine.hasRequest() ) this._executeHook(); + if ( engine.hasRequest() ) engine.start(); }; Paloma.isExecuted = function(){ - return this.engine.lastRequest().executed; + return engine.lastRequest().executed; }; })(window.Paloma);