GRIT
Grit is the Model third of the traditional Model-View-Controller webapp trinity. It's asynchronous and evented, and usable both in the browser and in NodeJS; think of it as a leaner Backbone with a more Node-friendly API.
Grit has a single hard dependency, but only in browsers: it needs
an implementation of EventEmitter stored on window.EventEmitter
.
A recommended EventEmitter implementation can be found
here. On NodeJS servers,
Grit has no dependencies.
Some may find Grit's Node-inspired callback system clunky or undesirable; glow, a Heavy Flow-based flow control plugin for Grit, comes highly recommended.
Sample
In pure JS:
var User = Model; User; User; var user = 'reissbaker';user;user;
Or, in CoffeeScript:
class User extends Model
@required 'username'
@validate 'username', (username) ->
typeof username == string
constructor: (username) ->
super username: username
user = new User 'reissbaker'
user.on 'change:username', (user, oldUsername, newUsername) ->
alert "changing username from #{oldUsername} to #{newUsername}"
user.set 'username', 'rekabssier'
API
The API follows the NodeJS EventEmitter API, and the events emitted are inspired by Backbone.
Models
Constructor
new Model(properties, isNew, finishedCallback)
, whereproperties
is a hash of properties,isNew
is an optional boolean that tells the constructor whether this is a new model that should be created in the database or is an existing model being loaded into memory, andfinishedCallback
is a callback that gets called once the model has been persisted in the database (if the model is new -- otherwise, the callback won't do anything, since the model doesn't get created). Creates a new Model object, and will set the properties according to the properties hash passed in. Please note that if you mark properties as required withModel.required
, you must either pass their initial values into the constructor or set initial values for them withModel.defaults
.
Instance Methods
model.on(evt, handler)
, ormodel.addListener(evt, handler)
add an event handler to the object. Model objects emit"change:p"
events, wherep
is the name of the property being changed. Event handlers should be of the formfunction(model, oldValue, newValue)
, wheremodel
is the model being changed,oldValue
is the previous value for the property being listened to, andnewValue
is the new value about to be set for the property being listened to.model.removeListener(e, handler)
removes an event handler.model.get(property, callback)
gets a named property and passes it to the callback.callback
should be of the formfunction(err, data)
, like most NodeJS callbacks.model.set(property, value[, silent, callback])
sets a property. Passing a truthy value as thesilent
parameter suppresses a change event; otherwise, achange:property
event will be emitted, whereproperty
is the value passed in as theproperty
parameter. The callback will be called once the set has propagated to the server or DB through theModel.update
method. Callbacks should be of the formfunction(err)
.model.destroy(callback)
destroys the model on the server or DB by proxying out toModel.destroy
. The callback will be called when the destruction has propagated to the server or DB, and should be of the formfunction(err)
.model.loadAll(callback)
loads all properties set as being on the class inModel.has
by proxying out to class methodModel.read
.callback
(optional) is of formfunction()
, and gets called once all of the properties have been loaded.
Class Methods
Syncing
Model.create(model, data, callback)
is the method to override for syncing model creation.model
is the model itself, anddata
is the property data in the raw.callback
is a function of the formfunction(err)
, and should be called once the server or DB is updated.Model.read(model, data, property, callback
is the method to override for reading individual properties from the server or DB.model
is the model being read from,data
is the model's data in the raw (you probably don't need to touch it!),property
is the property currently being read, andcallback
is a callback of the formfunction(err, data)
, and you should pass successfully-retrieved data to it (or call it with an error).Model.update(model, data, property, callback)
is the method to override for updating individual properties on the server.model
is the model currently being updated,data
is the model's data in the raw (grab the property data from there, rather than asynchronously trying to get it with get),property
is the property currently in need of syncing, andcallback
is a function of the formfunction(err)
, which you should call (without an error) on successful completion, or with an error upon an error.Model.destroy(model, data, callback)
is the method to override for syncing model destruction.model
is the model currently being destroyed,data
is its property data in the raw, andcallback
is a function of the formfunction(err)
, which should be called once the server or DB is updated.Grit.find(findArg, callback)
is the method to override for finding and loading entire models from the DB.findArg
can be whatever you want, andcallback
should presumably be some sort of function that gets the model passed into it!
Property defaults, assertions
Model.defaults(defaultsHash)
accepts a hash of default values to set for properties on model construction. If you don't specify default values for required properties, you must pass them into the constructor.Model.required(properties...)
marks properties as required. All required properties that do not have default values set must be passed at initialization into the Model constructor. If a required property is missing, all calls toset
will fail to validate.Model.unrequired(properties...)
unmarks properties previously marked as being required usingModel.required
.Model.has(properties...)
marks the model as having the properties, although without necessarily requiring them to be present to pass validation. ForloadAll
to work correctly, all properties must have been specified withModel.has
.Model.lacks(properties...)
unmarks properties previously marked as being had usingModel.has
.Model.validate(property, validator)
adds a validation callback to a property. Validation callbacks must be of the formfunction(value)
, and thevalue
that gets passed in is the new value being set. If all validators of a property return truthy values, the property will successfully be set; otherwise, it won't.
Inheritance
Model.extend(constructorFunction)
makes it easy for normal JS classes to inherit from Grit's Models. Just pass the constructor function toextend
, and don't forget to callModel.call(this)
(orSubClass.call(this)
) on the first line of the constructor function. If you're using CoffeeScript, just use the nativeextends
keyword, and if you override the constructor, don't forget to callsuper
before trying to access any Model methods.
Placeholders
Creation
placeholder(findArg, ModelClass)
takes any piece of data for thefindArg
and a class that extends fromModel
as theModelClass
argument. Creates and returns a Placeholder that will be able to proxy out to theModelClass
'sfind
method by passing thefindArg
, and load specified Models only as needed.
Loading
placeholderInstance.load(callback)
loads the Model specified in the creation function, if possible.callback
should be of the formfunction(err, model)
, and will be called with the loaded model once it's ready.
Collections
Constructor
new Collection(models)
, wheremodels
is an optional array of models. Creates a new Collection containing the models.
Instance methods
collection.on(evt, handler)
orcollection.addListener(evt, handler)
adds an event handler to the object. Collections forward all events from their contained models, and also fireadd
andremove
events for functions of the formfunction(element)
, whereelement
is what is being added or removed.collection.removeListener(evt, handler)
removes an event handler.collection.push(options, element, callback)
, whereoptions
is an optional hash,element
is a Model or Placeholder, andcallback
is an optional callback of the formfunction(err, model)
. This method pushes an element into the collection. If an options hash is provided and itsforceLoad
key is true, it will load any Placeholders into full Models and save them to the local cache.callback
gets called once all loading is completed, or if no loading was done, as soon as the data is pushed in.collection.pop(options, callback)
, whereoptions
is an optional hash andcallback
is an optional callback of the formfunction(err, model)
. Pops an element from the dataset. If an options hash is provided and itsforceLoad
key is true, the method will load any Placeholders into full Models.callback
is called once all loading is completed, or if no loading was done then as soon as the data is popped out.collection.pushFront(options, element, callback)
is exactly the same ascollection.push
, except that it pushes to the front of the dataset.collection.popFront(options, callback)
is exactly the same ascollection.pop
, except that it pops from the front of the dataset.collection.set(index, options, element, callback)
, whereindex
is a number,options
is an optional hash,element
is a Model or Placeholder, andcallback
is an optional callback of the formfunction(err, model, removed)
. Sets the index in the collection to the element passed in. If an options hash is provided and itsforceLoad
key is true, will load any Placeholders seen -- including any being overwritten -- into full Models. The callback is called once all loading has completed, or if no loading is done then as soon as the element is in the dataset.collection.remove(something, options, callback)
, wheresomething
is either a numeric index, a Placeholder, or a Model,options
is an optional hash, andcallback
is an optional callback of the formfunction(err, model)
. If given an index, removes the item at the index. If given a Placeholder or Model, searches for the item given and removes it. BE AWARE: if an options hash is provided and itsforceLoad
key is set to true, and a Model or Placeholder is passed in, the entire dataset may be loaded. If an index is passed in, only the item at that index will be loaded. Thecallback
will be called as soon as any loading is completed, or if no loading was done then as soon as the item is removed.collection.at(index, options, callback)
, whereindex
is a number,options
is an optional hash, andcallback
is a function of the formfunction(err, model)
. Passes the element at the index in the dataset to the callback. If an options hash is given and itsforceLoad
key is true, will load any Placeholders found into full Models and store them in the local cache.callback
will be called as soon as loading is completed, or if no loading was done it will be called immediately.collection.length()
returns the size of the dataset.collection.forEach(options, fn, callback)
, whereoptions
is an optional hash,fn
is a function of the formfunction(err, model, index)
that will be run on every item in the dataset, andcallback
is an optional function of the formfunction()
. Runsfn
on every item in the dataset. If an options hash is provided and itsinOrder
key is true, the function will be called in order over the dataset; otherwise, it may run in order or out of order (theindex
passed in will always be the correct index, however). If the options hash'sforceLoad
key is true, every Placeholder in the collection will be loaded into full Models and saved to the local cache.callback
will be called oncefn
has finished running on every element and all loading is complete.
LICENSE
GPL v3. Check LICENSE.txt and "GNU General Public License".txt for full details.