diff --git a/test_app/app/assets/javascripts/application.js b/test_app/app/assets/javascripts/application.js index 42fc34c..232a5fe 100644 --- a/test_app/app/assets/javascripts/application.js +++ b/test_app/app/assets/javascripts/application.js @@ -31,9 +31,29 @@ var blank = function(){}; Paloma.controller('Application', { + + // before: [ + // 'all -> logRequest', + // 'show index -> askUser changeBackground' + // ], + + before: [ + 'all -> performThis', + 'show -> doSomething' + ], + index: function(){ console.log('Inherited'); + }, + + doSomething: function(){ + console.log('Do something'); + }, + + performThis: function(){ + console.log('Perform This!'); } + }); Paloma.controller('Main < Application', { @@ -44,7 +64,7 @@ Paloma.controller('Main < Application', { }); -Paloma.controller('OtherMain', { +Paloma.controller('OtherMain < Application', { show: blank, otherAction: blank, multiple_calls_2: blank diff --git a/test_app/spec/javascripts/before_callback_performer_spec.js b/test_app/spec/javascripts/before_callback_performer_spec.js new file mode 100644 index 0000000..2de9565 --- /dev/null +++ b/test_app/spec/javascripts/before_callback_performer_spec.js @@ -0,0 +1,79 @@ +describe('Paloma.BeforeCallbackPerformer', function(){ + describe('#perform(action)', function(){ + + var Controller = Paloma.controller('MyController', { + before: [ + 'all -> initialize doThat', + 'singleCallback unknown -> doSomething', + 'multiCallback -> doSomething doAnotherThing' + ], + + initialize: function(){ + this.didWhat = []; + }, + + did: function(what){ return this.didWhat.indexOf(what) >= 0; }, + + noCallback: function(){ console.log('I have no callback.'); }, + singleCallback: function(){ console.log('Single callback.'); }, + multiCallback: function(){ console.log('Multiple callbacks.')}, + + doThat: function(){ this.didWhat.push('that'); }, + doSomething: function(){ this.didWhat.push('something'); }, + doAnotherThing: function(){ this.didWhat.push('anotherThing') } + }); + + function itPerformsCallbackForAll(controller){ + it('performs callback for all', function(){ + expect( controller.did('that') ).toBeTruthy(); + }); + }; + + describe('when there is no matched callback', function(){ + var controller = new Controller(), + performer = new Paloma.BeforeCallbackPerformer(controller); + + performer.perform('noCallback'); + + it('will not perform any callback', function(){ + expect( controller.did('something') ).toBeFalsy(); + }); + + itPerformsCallbackForAll(controller); + }); + + describe('when there is one matched callback', function(){ + var controller = new Controller(), + performer = new Paloma.BeforeCallbackPerformer(controller); + + performer.perform('singleCallback'); + + it('will perform the matched callback', function(){ + expect( controller.did('something') ).toBeTruthy(); + }); + + itPerformsCallbackForAll(controller); + }); + + describe('when there is more than one matched callbacks', function(){ + var controller = new Controller(), + performer = new Paloma.BeforeCallbackPerformer(controller); + + performer.perform('multiCallback'); + + it('will perform all the matched callbacks', function(){ + expect( controller.did('something') && controller.did('anotherThing') ). + toBeTruthy(); + }); + + it('will perform the callbacks in order of definition', function(){ + expect(controller.didWhat).toEqual([ + 'that', 'something', 'anotherThing' + ]); + }); + + itPerformsCallbackForAll(controller); + }); + + }); +}); diff --git a/vendor/assets/javascripts/paloma/base_controller.js b/vendor/assets/javascripts/paloma/base_controller.js index 2d265be..7d1bad3 100644 --- a/vendor/assets/javascripts/paloma/base_controller.js +++ b/vendor/assets/javascripts/paloma/base_controller.js @@ -1,3 +1,8 @@ Paloma.BaseController = function(params){ this.params = params; }; + +Paloma.BaseController.prototype = { + before: [] +}; + diff --git a/vendor/assets/javascripts/paloma/before_callback_performer.js b/vendor/assets/javascripts/paloma/before_callback_performer.js new file mode 100644 index 0000000..7ee38c5 --- /dev/null +++ b/vendor/assets/javascripts/paloma/before_callback_performer.js @@ -0,0 +1,69 @@ +Paloma.BeforeCallbackPerformer = function(controller){ + this.controller = controller; + this.entries = controller.before; + this.action = null; +}; + +Paloma.BeforeCallbackPerformer.prototype = { + + perform: function(action){ + this.action = action; + this._executeCallbacks(); + }, + + _executeCallbacks: function(){ + for (var i = 0, n = this._callbacks().length; i < n; i++) + this._executeCallback( this._callbacks()[i] ); + }, + + _executeCallback: function(name){ + var callback = this.controller[name]; + if (callback) callback.call(this.controller); + }, + + _callbacks: function(){ + if (this._callbackList) return this._callbackList; + + this._callbackList = []; + + for (var i = 0, n = this.entries.length; i < n; i++){ + var entry = this.entries[i]; + + this._callbackList = + this._callbackList.concat( this._getCallbacksIfForAction(entry) ); + } + + return this._callbackList; + }, + + _getCallbacksIfForAction: function(entry){ + var parsedEntry = this._parseEntry(entry); + + if ( + this._actionIsOn(parsedEntry.actions) || + this._allIsOn(parsedEntry.actions) + ) + return parsedEntry.callbacks; + + return []; + }, + + _actionIsOn: function(actions){ + return actions.indexOf(this.action) != -1; + }, + + _allIsOn: function(actions){ + return actions.indexOf('all') != -1; + }, + + _parseEntry: function(entry){ + var parts = entry.split('->'), + data = {actions: [], callbacks: []}; + + if (parts[0]) data.actions = parts[0].trim().split(' '); + if (parts[1]) data.callbacks = parts[1].trim().split(' '); + + return data; + } + +}; diff --git a/vendor/assets/javascripts/paloma/engine.js b/vendor/assets/javascripts/paloma/engine.js index f9aeb54..34c55f5 100644 --- a/vendor/assets/javascripts/paloma/engine.js +++ b/vendor/assets/javascripts/paloma/engine.js @@ -40,10 +40,14 @@ Paloma.Engine.prototype = { }, _executeActionOf: function(controller){ - var callback = controller[ this._request.action ]; + var action = controller[ this._request.action ]; + + if (action){ + var callbackPerformer = new Paloma.BeforeCallbackPerformer(controller); + callbackPerformer.perform( this._request.action ); + + action.call(controller); - if (callback){ - callback.call(controller); this._lastRequest.executed = true; } }, diff --git a/vendor/assets/javascripts/paloma/index.js b/vendor/assets/javascripts/paloma/index.js index 06de974..c080857 100644 --- a/vendor/assets/javascripts/paloma/index.js +++ b/vendor/assets/javascripts/paloma/index.js @@ -1,5 +1,6 @@ //= require ./init.js //= require ./base_controller.js //= require ./controller_builder.js +//= require ./before_callback_performer.js //= require ./engine.js //= require ./paloma.js