Skip to content

Commit

Permalink
better apply support
Browse files Browse the repository at this point in the history
  • Loading branch information
jamuhl committed Jan 20, 2012
1 parent ff04ebf commit cc23eae
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 55 deletions.
2 changes: 1 addition & 1 deletion Jakefile.js
Expand Up @@ -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": [
Expand Down
137 changes: 114 additions & 23 deletions README.md
Expand Up @@ -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`.

Expand Down Expand Up @@ -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`:

Expand All @@ -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:

Expand All @@ -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:

Expand All @@ -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({
Expand Down
7 changes: 0 additions & 7 deletions backboneCQRS-0.1.min.js

This file was deleted.

26 changes: 17 additions & 9 deletions 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(){

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}

});
Expand Down
5 changes: 5 additions & 0 deletions backboneCQRS-0.2.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 14 additions & 4 deletions src/backboneCQRS.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}

});
Expand Down
15 changes: 4 additions & 11 deletions test/eventDenormalizerTest.js
Expand Up @@ -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();
});
Expand All @@ -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();

}

});
Expand Down

0 comments on commit cc23eae

Please sign in to comment.