- ×
Marilyn is a client side, Socket.IO driven, Pub/Sub, model layer with a query system similar to Mongoose.
Filed under dataShow AllMarilyn
Marilyn is a client side, WebSocket driven, Pub/Sub, model layer with a query system similar to Mongoose.
Angular, Backbone, Ember, and many other libraries provide model layers which are AJAX driven. While variations on these models exist they are usually only useful if you're using the entire framework they are built to work with.
Marilyn can work with any framework, or by itself if you just need more data abstraction.
Installation
Install the module with bower:
$ bower install marilyn
Or download it from GitHub, extract it, and copy the files into your application.
Intalling with Script Tags
Include a script for the
marilyn.js
ormarilyn-min.js
file after a script for it's dependency,underscore.js
.Upon including the
marilyn.js
file a globalmarilyn
object will be available.Intalling with AMD
Marilyn can also be loaded using any AMD compliant module loader such as RequireJS.
Marilyn's only dependency is
underscore
.When using Marilyn with AMD you MUST load the models before using them inside controllers. This can be done as follows.
require(['model/myModel'], function(myModel) { // configure Marilyn and other core libraries require(['controller/myController'], function(myController) { // you can now use the model in your controller }); });
Usage
Configure Socket.IO
Before using Marilyn with Socket.IO you have to configure Marilyn to use Socket.IO's socket connection. Lets use the client side example connection from the Socket.IO website to demonstrate this.
<script src="/socket.io/socket.io.js"></script> <script> var socket = io.connect('http://localhost'); </script>
This creates a global variable called
socket
. This variable should be passed to Marilyn so Marilyn can use the Socket.IOon
andemit
methods.<script> marilyn.config(socket); </script>
After this Marilyn has
on
andemit
methods that we should call instead of the Socket.IO methods. This allows us to centralize all data querying and data fetching methods to Marilyn.Creating Model
Like Mongoose, Marilyn creates models using the
model
method.var MyModel = marilyn.model('someModelName');
MyModel
is now a Marilyn model, containing query and event methods.You can also create a model by passing the
marilyn.model
methods a second parameter, a callback function. Within this callback functionthis
represents the model that has been created.var MyModel = marilyn.model('someModelName', function(){ // "this" is the same as MyModel });
Like Mongoose, the Marilyn model created, called
someModelName
, can now be accessed from the globalmarilyn
object.This allows you to use self executing functions to create a model and not pollute the global scope.
// myModel.js (function(){ var NonPollutingModel = marilyn.model('someModelName', function(){ this.on('someSocketEvent', function(data){ // do something with data in model this.inform('someBrowserEvent', data); }); }); NonPollutingModel.on('someOtherSocketEvent', function(data){ // do something else }); })();
// myController.js (function(){ var MyModel = marilyn.model('someModelName'); MyModel.receive('someBrowserEvent', function(){ // do something with data in controller }); })();
Adding Data to Models
All models have a
_collection
variable.Setting the
_collection
variable directly without the CRUD methods or the collection setter will not create this__id
property and Marilyn will not function properly.This variable is an array of all the objects you have stored in your frontend model.
To populate this variable you can use the built in CRUD methods listed below, or the
collection
setter.If you use the CRUD methods various built in callbacks will be run. If you use the
collection
setter these callback functions won't be called.marilyn.model('someModelName', function(){ this.on('someSocketEvent', function(data){ // sets the _collection array // this won't trigger any callbacks this.collection(data); }); this.on('someOtherServerEvent', function(data){ // pushes a new object into the _collection array and performs many other tasks // this will trigger all the "create" callbacks this.create(data); }); });
When new objects are added to the
_collection
variable a property of__id
is added to them so Marilyn can internally track them.Event Handlers
Marilyn has four types of event handlers, socket events, browser events, befores, and afters.
Socket events are for communicating from your model to a socket server, or from a socket server to your model.
Browser events are for communicating between your model and controller, or client side logic layer.
Befores run before a query method is executed.
Afters run after a query method is executed.
Socket events and browser events have two methods, an event listener and an event dispatcher.
Socket Events
The socket event methods behave the same events as Socket.IO.
They are
on
andemit
.Refere to Socket.IO documentation to understand how these work.
Browser Events
Browser event methods are
receive
andinform
. They act very similarly to Socket.IO'son
andemit
.They can send data and receive data with callback functions.
// myModel.js marilyn.model('someModelName', function(){ this.inform('modelReady', { 'someKey':'someValue' }); });
// myController.js var MyModel = marilyn.model('someModelName'); MyModel.receive('modelReady', function(data){ // do something here // data is the object passed from the inform method });
All query events inform receivers after completion. This is best shown in the next example.
Befores and Afters
Befores and afters are similar to Mongoose's
pre
andpost
events. Befores are triggered before all querys, and afters are after the query.Befores and afters are triggered from
save
,create
,read
,readOne
,update
, anddelete
.Sometimes multiple befores and afters can be triggered by one CRUD method being invoked, for example the
save
method can trigger befores and afters forcreate
andupdate
in addition to befores and afters forsave
events.To create a before or after you use the
before
orafter
method passing it two parametersThe first parameter is either a string of a single event name (listed above) or an array of strings of event names.
The second paramter is a callback function.
All callbacks of befores and afters are passed data that they can manipulate and a next method, which must be called in order to progress the flow control. Callbacks are passed different sets of data depending on the event being listened for, which are listed below.
Save / Create
before callback
data:Object, next:Function
data
is the object being created. It is useful for validating data or adding default fields to objects.after callback
data:Object, next:Function
data
is the object that has been created. It is useful for altering data before it's returned to the callback or syncing the data with a server.Read
before callback
query:Object, next:Function
query
is what is being used to search for records. It is useful for restricting access to records.after callback
data:Array, next:Function
data
is an array of objects found from the query. It is useful for adding custom fields or methods.Read One
before callback
query:Object, next:Function
query
is the query being used to read the one object. It is useful for restricting access to records.after callback
data:Object, next:Function
data
is an the single object found from the query. It is useful for adding custom fields and methods.Update
before callback
searchQuery:Object, updateQuery:Object, next:Function
searchQuery
is the query being used to read the objects. It is useful for restricting access to records.updateQuery
is the changes that will be made to all objects found. It is useful for restricting access to certain field updates.after callback
data:Array, next:Function
data
is an array of objects that have been updated. It is useful for adding custom fields and methods or syncing with a server.Delete
before callback
searchQuery:Object, next:Function
searchQuery
is the query being used to read the objects. It is useful for restricting access to records.after callback
data:Array, next:Function
data
is an array of objects that have been deleted. It is useful for syncing with a server.Querying Data with CRUD Methods
Each Marilyn model has a private variable called
_collection
, which can be populated with an array of data. All query methods query this variable.There are ten query methods,
create
,createSilent
,read
,readSilent
,readOne
,readOneSilent
,update
,updateSilent
,del
, anddelSilent
.All silent query methods don't trigger befores or afters.
Create
var myModel = new MyModel(); myModel.title = 'Star Wars'; myModel.director = 'George Lucas'; // calling the save method will trigger create befores and afters as well as save befores and afters myModel.save(function(err, result){ // result is the object created }); // OR var myModel = new MyModel({ 'title':'Star Wars', 'director':'George Lucas' }); // calling the save method will trigger create befores and afters as well as save befores and afters myModel.save(function(err, result){ // result is the object created }); // OR // calling the create method will trigger create befores and afters, but not saves MyModel.create({ 'title':'Star Wars', 'director':'George Lucas' }, function(err, result){ // result is the object created });
Read
// calling the read method will trigger read befores and afters // calling read without passing a query will read all MyModel.read(function(err, results){ // results is an array of all the objects in the collection }); // calling the read method will trigger read befores and afters MyModel.read({ 'director':'George Lucas' }, function(err, results){ // results is an array of all the objects found }); // calling this method will trigger read befores and afters MyModel.read({ 'director':'George Lucas' }, function(err, results){ // results is an array of all the objects found }); // calling this method will trigger readOne befores and afters MyModel.readOne({ 'id':1138 }, function(err, result){ // result is the single object found });
Update
// updates using readOne MyModel.readOne({ 'id':1138 }, function(err, result){ result.director = 'George Lucas'; // calling the save method will trigger update befores and afters as well as save befores and afters result.save(function(err, result){ // result is the updated object }); }); // calling this method will trigger update befores and afters MyModel.update({ 'id':1138 }, { 'propertyToUpdate':'someValue' }, function(err, results){ // results is an array of all the objects updated });
Delete
// calling this method will trigger delete befores and afters MyModel.del({ 'id':1138 }, function(err results){ // results is an array of all the objects deleted });
err
is always populated if nothing matches the query.Query methods don't directly call the server, you must call the server manually with
emit
either before or after query methods are invoked. This makesbefore
andafter
very useful for server integration.Dependencies
Marilyn requires Underscore >= 1.5.0. Get it from: http://underscorejs.org/
Author
Alan James: alanjames1987@gmail.com
License
Licensed under MIT.