A tiny framework for creating models in node.js based server code.
When writing server code that fetches and persists data to a backing store, be it MySQL, Redis, Riak etc. there are several features you want and a certain amount of boilerplate code that is needed. MnoVnoC is a simple framework that provides the following helper features:
The Model follows an Active record pattern: http://en.wikipedia.org/wiki/Active_record_pattern
npm install MnoVnoC
This is the meat of the module. The sections below explain how to declare, define and use models.
var Model = ;var Person = Model;var p = name: 'bob' age: 55 ;pname // bobpage // 55
At this point you have a working model, but you cannot perform any CRUD operations using this mode, to do so see the CRUD section below.
When you define a model you can specify defaults for the properties in the model. If these values are not passed in the constructor they will get set on the new model e.g.
var Model = Model;var Person = Model;var p = ;pname // frankpage // 50var p2 = name: 'bob' ;pname // bobpage // 50
One of the main things you want to be able to do in a model is validation of fields to make sure user values conform to the business rules of your model. You can explicity call validate() to do a check of the current state of the model, or when you call save() the validate() method is called before the model tries to save the data, you can check the error parameter in the save callback to see if there were any validation errors.
NOTE: you must always code validate() with a callback.
var Model = Model;var Person = Model;
var p =name: 'joe'age: 200;p;
var p =;p;
When you define a model, it comes with a field called "data" which is an object containing the following methods, create, fetch, update, destroy. If you try to call these default methods an exception will be throw. In your model definition you can override the data object and set the methods to connect and handle whatever backend store you are utilizing e.g.
var Person = Model;
IMPORTANT: You never call the data.XXX methods directly, they are called indirectly by other methods on the model, as explained below.
To fetch values from your backing store into a model you need to override the data.fetch function.
var Model = Model;var Person = Model;var p = id: 123 ;p;
NOTE: The options parameter is optional, but there may be cases where you want to pass in optional data that gets passed through to the data.XXX methods
To delete an instance of your model, you need to override the data.destroy method:
var Person = Model;var p = id: 1234 ;p;
To create or update an existing model, you call model.save(), it takes a callback and an options parameter (optional). Calling save can do one of two things, if the model represents a "new" object on the backend then data.create will be called, if the model represents an existing entity on the backend then data.update() will be called.
To distinguish between the two, if a model instance has a field called "id" then it is assumed the model represents an existing data item and update() is called, if the model instance does not have an "id" field, then it is assumed to be a new data item and "create" will be called.
An example of creating a new model
var Person = Model;// Because the model does not have an "id" value, it is assumed// to be new and so data.create will be calledvar p = name: 'bob' age: 55 ;p;
NOTE: In the create method, you will want to set model.id with the ID of the data from the backing store, before calling back from create so that the model instance now has an id field. If you don't do this then if you reuse the model instance and call save() again, create() will be called instead of update() since the model will still be considered "new" without an id field.
An example of updating an existing model
var Person = Model;// Since the model has an "id" property, it is considered to exist already on// the backend, hence any call to save() will direct to data.update() instead of// data.create()var p = id: 1234 name: 'frank' ;p;
Sometimes you want to know if a model is dirty, meaning some of the fields have changed since the model was last fetched, you may also want to know which of the fields have changed since the last time. You can access this information via Model.hasChanged() which returns true if the model has changed since it was last fetched, and Model.changed() is an object that contains the fields that have changed.
HOWEVER... in order to get this information, you need to update fields using the Model.set(name, value) function. If you set a value directly on an object e.g.
myPersonname = 'Pete';
This will not update the changed event, so instead, you need to update the object via the set() method e.g.
If you do this inside the update method you will get the hasChanged() and changed() information e.g.
By using getters/setters on your model, you can hide the ugly set(name, value) calls behind normal myPerson.name = 'Frank' syntax and still get the benefit of the changed() and hasChanged() information.
Below is an example of how you can use getters and setters.
/*** This example shows you how you can use getters/setters to make your* model easy to use and get changed information*/var Model = Model;var Person = Model;var p =id: 1234name: 'frank'age: 95salary: 10000;// Take a peek at the current state of the modelconsoledirp;// Lets update somethingpage = 96;psalary = 15000;// We can see what has changedconsole;consoledirp;// save the updated model, since this model has an id, it is assumed// it is an existing model that is being updated, so it goes into the// data.update methodp;
NOTE: Hopefully you read the comments, but if you call set() with a parameter name that starts with _ when you call changed() the name of the fields in the changed() object has the _ removed.
Any model you define that derives from Model, will have event support, since Models inherit from the node.js EventEmitter class.
To trigger an event on your model use the "emit" method e.g.
var Model = ;var Person = Model;var p = name: 'bob' age: 55 ;p;p; // event raised at this point
One way to tell if a models data has been fetched from the backing store is to check for the presence of a field called refreshedAt on the model. Every time fetch() is successfully called the refreshedAt value contains an updated Date value e.g.
var p = id: 12345 ;console // undefinedp;
No collection support at the moment, if you need one you can add it :)
For more examples, see the unit tests
git clone firstname.lastname@example.org:markdaws/MnoVnoC.gitcd MnoVnoCnpm installnpm test