Skip to content
Browse files

better apply support

  • Loading branch information...
1 parent ff04ebf commit cc23eae354009ec44007a7e1f76c7c73b9c943c6 @jamuhl committed
Showing with 155 additions and 55 deletions.
  1. +1 −1 Jakefile.js
  2. +114 −23 README.md
  3. +0 −7 backboneCQRS-0.1.min.js
  4. +17 −9 backboneCQRS-0.1.js → backboneCQRS-0.2.js
  5. +5 −0 backboneCQRS-0.2.min.js
  6. +14 −4 src/backboneCQRS.js
  7. +4 −11 test/eventDenormalizerTest.js
View
2 Jakefile.js
@@ -8,7 +8,7 @@ task('build', [], function(debug) {
// a basic smoosh configuration object
smoosh.config({
- "VERSION": "0.1",
+ "VERSION": "0.2",
"JAVASCRIPT": {
"DIST_DIR": "./",
"backboneCQRS": [
View
137 README.md
@@ -9,7 +9,7 @@ To use CQRS on the clientside and inside Backbone.js we will need to push _event
to the browser. You can achieve this via websockets, flash, long polling or any
other technique around.
-## Initialization
+## INITIALIZATION
To configure Backbone.CQRS you got to init the `Backbone.CQRS.hub`.
@@ -50,7 +50,7 @@ You can override a few values on initialisation:
});
-## Wire up commands and events to/from sever
+### Wire up commands and events to/from sever
The interface to Backbone.CQRS is provided through `Backbone.CQRS.hub`:
@@ -64,7 +64,27 @@ The interface to Backbone.CQRS is provided through `Backbone.CQRS.hub`:
mySocket.emit('commands', data);
});
-## Denormalize event data to you model
+## EVENT HANDLING
+
+### Denormalize _create_ events which not yet have a model
+
+For creational events which aren't applied to an existing model you could
+override the _handle_ function in the eventdenormalizer:
+
+ var PersonCreateHandler = Backbone.CQRS.EventDenormalizer.extend({
+ handle: function(evt) {
+ // do something
+ var person = new person(evt.payload);
+ app.persons.add(person);
+ }
+ });
+
+ var personCreateHandler = new PersonCreateHandler({
+ forModel: 'person',
+ forEvent: 'personCreated'
+ });
+
+### Denormalize event data to matching model
First create a denormalizer:
@@ -78,39 +98,108 @@ First create a denormalizer:
var me = new person({id: '1'});
me.bindCQRS();
-all _personChanged_ events for id = 1 will be applied to the personModel by simply
-set the event data to the model. You could override the apply function like this to
-get more control:
+all _personChanged_ events payload attributes for id = 1 will be applied to the personModel by simply
+set the event data to the model.
- var person = Backbone.Model.extend({
+You could change this behavior by:
- modelName: 'person',
+#### 1) change the attribute for data
- apply: function(data) {
- if (data.name === 'personChanged') {
- this.set(data.payload);
- }
+By default Backbone.CQRS will apply `event.payload` to model.
+
+ var PersonCreateDenormalizer = Backbone.CQRS.EventDenormalizer.extend({
+ defaultPayloadValue: 'myAttribute' // or 'myAttribute.child1.child2' if it's nested
+ });
+
+ var personCreatedHandler = new PersonCreateDenormalizer({
+ forModel: 'person',
+ forEvent: 'personChanged'
+ });
+
+#### 2) override the parse function
+
+ var PersonCreateDenormalizer = Backbone.CQRS.EventDenormalizer.extend({
+
+ parse: function(evt) {
+
+ // evt is a Backbone.CQRS.Event (extending model) so:
+ var data = evt.toJSON();
+
+ return {
+ value1: data.myAttr.child,
+ value2: data.myAttr2.child.child
+
+ //...
+ };
}
- });
-For creational events which aren't applied to an existing model you could
-override the _handle_ function in the eventdenormalizer:
+ });
- var PersonCreateHandler = Backbone.CQRS.EventDenormalizer.extend({
- handle: function(evt) {
- // do something
- var person = new person(evt.payload);
- app.persons.add(person);
+ var personCreatedHandler = new PersonCreateDenormalizer({
+ forModel: 'person',
+ forEvent: 'personChanged'
+ });
+
+#### 3) override the apply function in denormalizer
+
+ var PersonCreateDenormalizer = Backbone.CQRS.EventDenormalizer.extend({
+
+ apply: function(data, model) {
+ model.set(data.payload.myAttr);
+ },
+
+ // optional override parse too
+ parse: function(evt) {
+ // ...
}
+
});
- var personCreateHandler = new PersonCreateHandler({
+ var personCreatedHandler = new PersonCreateDenormalizer({
forModel: 'person',
- forEvent: 'personCreated'
+ forEvent: 'personChanged'
+ });
+
+This way you can control the apply function for the model inside of the eventdenormalizer.
+
+If you prefer to have the apply function inside you model you could override this
+too, but be aware all events will be routed to the same apply function, so you will have to distinguish events inside your models apply function!
+
+You could override the apply function like this to
+get more control:
+
+ var PersonCreateDenormalizer = Backbone.CQRS.EventDenormalizer.extend({
+
+ parse: function(evt) {
+ return evt; // return the pure event object
+ }
+
+ });
+
+ var personCreatedHandler = new PersonCreateDenormalizer({
+ forModel: 'person',
+ forEvent: 'personChanged'
});
-## send commands
+ var person = Backbone.Model.extend({
+
+ modelName: 'person',
+
+ apply: function(evt) {
+ if (evt.name === 'personChanged') {
+ this.set(evt.payload);
+ }
+
+ }
+ });
+
+ var me = new person({id: '1'});
+ me.bindCQRS();
+
+## COMMAND HANDLING
+
+### send commands
To send commands just:
@@ -125,6 +214,8 @@ To send commands just:
// emit it
cmd.emit();
+### observe commands
+
if you want to react on events in respond to a command you can:
var cmd = new Backbone.CQRS.Command({
View
7 backboneCQRS-0.1.min.js
@@ -1,7 +0,0 @@
-// Backbone.js 0.5.3
-// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
-// Backbone may be freely distributed under the MIT license.
-// For all details and documentation:
-// http://documentcloud.github.com/backbone
-
-((function(){var a=this,b=a.Backbone;b.CQRS={};var c=a._;!c&&typeof require!="undefined"&&(c=require("underscore")._);var d=a.jQuery||a.Zepto,e=d.noop;b.CQRS.Message=b.Model.extend({url:e,fetch:e,save:e,destroy:e});var f=b.CQRS.Message.extend({});b.CQRS.Command=b.CQRS.Message.extend({emit:function(){b.CQRS.hub.emit(b.CQRS.hub.commandsChannel,this.parse(this.toJSON()))},parse:function(a){return a},observe:function(a){b.CQRS.eventHandler.observe(this.id,a)}});var g=b.CQRS.hub={commandsChannel:"commands",defaults:{commandsChannel:"commands",eventsChannel:"events",eventNameAttr:"name",eventModelIdAttr:"payload.id",eventResponseToCommandId:"commandId"},init:function(a){var b=this;this.initialized||(this.initialized=!0,a=c.extend(this.defaults,a),a.parseEvent&&(this.parseEvent=a.parseEvent),a.getCommandId&&(this.getCommandId=a.getCommandId),this.commandsChannel=a.commandsChannel,this.on(a.eventsChannel,function(c){var d=new f;d.set(this.parseEvent(c));var e=d.toJSON();d.name=i(e,a.eventNameAttr),d.id=i(e,a.eventModelIdAttr),d.cmdId=b.getCommandId(e,a.eventResponseToCommandId),this.emit("dispatchEvent",d)}))},parseEvent:function(a){var b=a;return typeof b=="string"&&(b=JSON.parse(b)),b},getCommandId:function(a,b){return i(a,b)}};c.extend(g,b.Events),g.on=g.bind,g.emit=g.trigger,b.CQRS.EventDenormalizer=function(a){a=a||{},a.forEvent&&(this.forEvent=a.forEvent),a.forModel&&(this.forModel=a.forModel),this.forEvent&&this.forModel&&this.register.apply(this),this.initialize.apply(this,arguments)},c.extend(b.CQRS.EventDenormalizer.prototype,b.Events,{initialize:e,handle:function(a){a.id&&this.trigger("change:"+a.id,this.parse(a))},parse:function(a){return a},register:function(a,c){this.forEvent=a||this.forEvent,this.forModel=c||this.forModel,b.CQRS.eventHandler.register(this)}}),b.CQRS.EventDenormalizer.extend=b.Model.extend;var h=b.CQRS.EventDenormalizer.extend({initialize:function(){this.denormalizers=[],this.observedCommands=[],b.CQRS.hub.on("dispatchEvent",function(a){this.handle(a)},this)},getDenormalizer:function(a,b){return a?c(this.denormalizers).filter(function(b){return b.forEvent==a}):b?c(this.denormalizers).filter(function(a){return a.forModel==b}):null},handle:function(a){var b=this.getPendingCommand(a);b&&(b.callback(a),this.removePendingCommand(b));var d=this.getDenormalizer(a.name);c(d).each(function(b){b.handle(a)})},bind:function(a,b,d){if(a.indexOf(":")<0)return!1;var e=a.split(":"),f=e[0],g="change:"+e[1],h=this.getDenormalizer(null,f);c(h).each(function(a){a.bind(g,b,d)})},unbind:function(a,b){if(a.indexOf(":")<0)return!1;var d=a.split(":"),e=d[0],f="change:"+d[1],g=this.getDenormalizer(null,e);c(g).each(function(a){a.unbind(f,b)})},observe:function(a,b){this.observedCommands.push({id:a,callback:b})},getPendingCommand:function(a){return c.detect(this.observedCommands,function(b){return b.id==a.cmdId})},removePendingCommand:function(a){var b=c.indexOf(this.observedCommands,a);this.observedCommands.splice(b,1)},register:function(a){this.denormalizers.push(a)}});b.CQRS.eventHandler=new h,b.Model=b.Model.extend({modelName:null,bindCQRS:function(a){a&&(this.modelName=a);if(!this.modelName)return;var c=this.id||this.cid;b.CQRS.eventHandler.bind(this.modelName+":"+c,this.apply)},unbindCQRS:function(a){a&&(this.modelName=a);if(!this.modelName)return;var c=this.id||this.cid;b.CQRS.eventHandler.unbind(this.modelName+":"+c,this.apply)},apply:function(a){this.set(a)}});var i=function(a,b){var c=b.split("."),d=0,e=a;while(c[d])e=e&&e[c[d]],d++;return e}})).call(this)
View
26 backboneCQRS-0.1.js → backboneCQRS-0.2.js
@@ -1,8 +1,6 @@
-// Backbone.js 0.5.3
-// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
-// Backbone may be freely distributed under the MIT license.
-// For all details and documentation:
-// http://documentcloud.github.com/backbone
+// Backbone.CQRS.js
+// (c) 2012 Jan Mühlemann
+// Backbone.CQRS may be freely distributed under the MIT license.
(function(){
@@ -131,18 +129,28 @@
// Set up all inheritable **Backbone.Router** properties and methods.
_.extend(Backbone.CQRS.EventDenormalizer.prototype, Backbone.Events, {
+ defaultPayloadValue: 'payload',
+
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize : noop,
handle: function(evt) {
if (evt.id) {
- this.trigger('change:' + evt.id, this.parse(evt));
+ this.trigger('change:' + evt.id, this.parse(evt), this.apply);
}
},
+ apply: function(data, model) {
+ model.set(data);
+ },
+
parse: function(evt) {
- return evt;
+ if (this.defaultPayloadValue) {
+ return dive(evt.toJSON(), this.defaultPayloadValue);
+ } else {
+ return evt.toJSON();
+ }
},
register: function(forEvt, forMdl) {
@@ -276,8 +284,8 @@
Backbone.CQRS.eventHandler.unbind(this.modelName + ':' + id, this.apply);
},
- apply: function(data) {
- this.set(data);
+ apply: function(data, funct) {
+ funct.apply(this, data, this);
}
});
View
5 backboneCQRS-0.2.min.js
@@ -0,0 +1,5 @@
+// Backbone.CQRS.js
+// (c) 2012 Jan Mühlemann
+// Backbone.CQRS may be freely distributed under the MIT license.
+
+((function(){var a=this,b=a.Backbone;b.CQRS={};var c=a._;!c&&typeof require!="undefined"&&(c=require("underscore")._);var d=a.jQuery||a.Zepto,e=d.noop;b.CQRS.Message=b.Model.extend({url:e,fetch:e,save:e,destroy:e});var f=b.CQRS.Message.extend({});b.CQRS.Command=b.CQRS.Message.extend({emit:function(){b.CQRS.hub.emit(b.CQRS.hub.commandsChannel,this.parse(this.toJSON()))},parse:function(a){return a},observe:function(a){b.CQRS.eventHandler.observe(this.id,a)}});var g=b.CQRS.hub={commandsChannel:"commands",defaults:{commandsChannel:"commands",eventsChannel:"events",eventNameAttr:"name",eventModelIdAttr:"payload.id",eventResponseToCommandId:"commandId"},init:function(a){var b=this;this.initialized||(this.initialized=!0,a=c.extend(this.defaults,a),a.parseEvent&&(this.parseEvent=a.parseEvent),a.getCommandId&&(this.getCommandId=a.getCommandId),this.commandsChannel=a.commandsChannel,this.on(a.eventsChannel,function(c){var d=new f;d.set(this.parseEvent(c));var e=d.toJSON();d.name=i(e,a.eventNameAttr),d.id=i(e,a.eventModelIdAttr),d.cmdId=b.getCommandId(e,a.eventResponseToCommandId),this.emit("dispatchEvent",d)}))},parseEvent:function(a){var b=a;return typeof b=="string"&&(b=JSON.parse(b)),b},getCommandId:function(a,b){return i(a,b)}};c.extend(g,b.Events),g.on=g.bind,g.emit=g.trigger,b.CQRS.EventDenormalizer=function(a){a=a||{},a.forEvent&&(this.forEvent=a.forEvent),a.forModel&&(this.forModel=a.forModel),this.forEvent&&this.forModel&&this.register.apply(this),this.initialize.apply(this,arguments)},c.extend(b.CQRS.EventDenormalizer.prototype,b.Events,{defaultPayloadValue:"payload",initialize:e,handle:function(a){a.id&&this.trigger("change:"+a.id,this.parse(a),this.apply)},apply:function(a,b){b.set(a)},parse:function(a){return this.defaultPayloadValue?i(a.toJSON(),this.defaultPayloadValue):a.toJSON()},register:function(a,c){this.forEvent=a||this.forEvent,this.forModel=c||this.forModel,b.CQRS.eventHandler.register(this)}}),b.CQRS.EventDenormalizer.extend=b.Model.extend;var h=b.CQRS.EventDenormalizer.extend({initialize:function(){this.denormalizers=[],this.observedCommands=[],b.CQRS.hub.on("dispatchEvent",function(a){this.handle(a)},this)},getDenormalizer:function(a,b){return a?c(this.denormalizers).filter(function(b){return b.forEvent==a}):b?c(this.denormalizers).filter(function(a){return a.forModel==b}):null},handle:function(a){var b=this.getPendingCommand(a);b&&(b.callback(a),this.removePendingCommand(b));var d=this.getDenormalizer(a.name);c(d).each(function(b){b.handle(a)})},bind:function(a,b,d){if(a.indexOf(":")<0)return!1;var e=a.split(":"),f=e[0],g="change:"+e[1],h=this.getDenormalizer(null,f);c(h).each(function(a){a.bind(g,b,d)})},unbind:function(a,b){if(a.indexOf(":")<0)return!1;var d=a.split(":"),e=d[0],f="change:"+d[1],g=this.getDenormalizer(null,e);c(g).each(function(a){a.unbind(f,b)})},observe:function(a,b){this.observedCommands.push({id:a,callback:b})},getPendingCommand:function(a){return c.detect(this.observedCommands,function(b){return b.id==a.cmdId})},removePendingCommand:function(a){var b=c.indexOf(this.observedCommands,a);this.observedCommands.splice(b,1)},register:function(a){this.denormalizers.push(a)}});b.CQRS.eventHandler=new h,b.Model=b.Model.extend({modelName:null,bindCQRS:function(a){a&&(this.modelName=a);if(!this.modelName)return;var c=this.id||this.cid;b.CQRS.eventHandler.bind(this.modelName+":"+c,this.apply)},unbindCQRS:function(a){a&&(this.modelName=a);if(!this.modelName)return;var c=this.id||this.cid;b.CQRS.eventHandler.unbind(this.modelName+":"+c,this.apply)},apply:function(a,b){b.apply(this,a,this)}});var i=function(a,b){var c=b.split("."),d=0,e=a;while(c[d])e=e&&e[c[d]],d++;return e}})).call(this)
View
18 src/backboneCQRS.js
@@ -129,18 +129,28 @@
// Set up all inheritable **Backbone.Router** properties and methods.
_.extend(Backbone.CQRS.EventDenormalizer.prototype, Backbone.Events, {
+ defaultPayloadValue: 'payload',
+
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize : noop,
handle: function(evt) {
if (evt.id) {
- this.trigger('change:' + evt.id, this.parse(evt));
+ this.trigger('change:' + evt.id, this.parse(evt), this.apply);
}
},
+ apply: function(data, model) {
+ model.set(data);
+ },
+
parse: function(evt) {
- return evt;
+ if (this.defaultPayloadValue) {
+ return dive(evt.toJSON(), this.defaultPayloadValue);
+ } else {
+ return evt.toJSON();
+ }
},
register: function(forEvt, forMdl) {
@@ -274,8 +284,8 @@
Backbone.CQRS.eventHandler.unbind(this.modelName + ':' + id, this.apply);
},
- apply: function(data) {
- this.set(data);
+ apply: function(data, funct) {
+ funct.apply(this, data, this);
}
});
View
15 test/eventDenormalizerTest.js
@@ -64,11 +64,9 @@ asyncTest("Pass event through denormalizer to model", function() {
initialize: function() {
- Backbone.CQRS.eventHandler.bind('myModel:4', function(evt) {
- equals(evt.name, 'myEvent4', 'get eventName');
- equals(evt.id, '4', 'get model id');
- equals(evt.get('name'), 'myEvent4', 'get eventName from attr');
- equals(evt.get('payload').project, 'Backbone.CQRS', 'get value from payload');
+ Backbone.CQRS.eventHandler.bind('myModel:4', function(data) {
+ equals(data.id, '4', 'get model id');
+ equals(data.project, 'Backbone.CQRS', 'get value from payload');
start();
});
@@ -94,14 +92,9 @@ asyncTest("Pass event through denormalizer to cqrs extended model", function() {
var myModel = Backbone.Model.extend({
apply: function(data) {
-
- equals(data.name, 'myEvent5', 'get eventName');
equals(data.id, '5', 'get model id');
- equals(data.get('name'), 'myEvent5', 'get eventName from attr');
- equals(data.get('payload').project, 'Backbone.CQRS', 'get value from payload');
-
+ equals(data.project, 'Backbone.CQRS', 'get value from payload');
start();
-
}
});

0 comments on commit cc23eae

Please sign in to comment.
Something went wrong with that request. Please try again.