# model ## About A `Model` represents the data of your application. Asteroid `Model`s are mostly used for validating interactions with a [DataSource](../data-source). Usually your models will correspond to a namespace in your data source (database table, http url, etc). The bulk of your application's business logic will be in your `Model` or Node.js scripts that require your model. ## Data Definition Language TODO ~ document ## API ### Defining Models The following assumes your have reference to a class that inherits from `Model`. The simplest way to get this is by using the [app API](../../readme.md#API). // define a model class using the app api var Color = app.define('color'); // provide an exact plural name var Color = app.define('color', {plural: 'colors'}); **Note:** If a plural name is not defined, the model will try to pluralize the singular form. #### MyModel.defineSchema(schema) Define the data the model represents using the data definition language. // define the color model var Color = app.define('color'); // define the schema for the Color model Color.defineSchema({ name: 'string', id: 'uid', tweets: 'array' }); ##### MyModel.dataSource(name, namespace) Set the data source for the model. Must provide a name of an existing data source. If the `namespace` is not provided the plural model name (eg. `colors`) will be used. // set the data source Color.dataSource('color-db', 'COLOR_NAMES'); **Note:** If you do not set a data source or a map (or both) the default data source will be used (an in memory database). #### MyModel.defineMap(map) Define a mapping between the data source representation of your data and your app's representation. // manually map Color to existing table columns Color.defineMap({ dataSource: 'color-db', // optional, will use model's data source table: 'COLOR_NAMES', // required map: { // optional if schema defined id: 'COLOR_ID', name: 'COLOR_NAME' } }); // mix in a mapping from another data source Color.defineMap({ dataSource: 'twitter', url: function(color) { return '/search?limit=5&q=' + color.name; }, map: { // provides the color.tweets property tweets: function(tweets) { return tweets; } } }); **Note:** You may define multiple maps for a single model. The model will combine the data for you. #### MyModel.discoverSchema(fn) Using the mapped data source, try to discover the schema of a table or other namespace (url, collection, etc). // use existing schema to map to desired properties Color.dataSource('color-db', 'COLOR_NAMES'); Color.discoverSchema(function (err, oracleSchema) { var schema = {tweets: 'array'}; var map = {dataSource: 'color-db', table: 'COLOR_NAMES'}; // inspect the existing table schema to create a mapping Object .keys(oracleSchema) .forEach(function (oracleProperty) { // remove prefix var property = oracleProperty.toLowerCase().split('_')[0]; // build new schema schema[property] = oracleProperty[oracleProperty]; // create mapping to existing schema map[property] = oracleProperty; }); Color.defineSchema(schema); Color.defineMap(map); }); ### Custom Methods There are two types of custom methods. Static and instance. **Static** Static methods are available on the Model class itself and are used to operate on many models at the same time. **Instance** Instance methods are available on an instance of a Model and usually act on a single model at a time. #### Defining a Static Method The following example shows how to define a simple static method. Color.myStaticMethod = function() { // only has access to other static methods this.find(function(err, colors) { console.log(colors); // [...] }); } #### Defining an Instance Method The following is an example of a simple instance method. Color.prototype.myInstanceMethod = function() { console.log(this.name); // red } #### Remotable Methods Both types of methods may be set as `remotable` as long as they conform to the remotable requirements. Asteroid will expose these methods over the network for you. ##### Remotable Requirements Static and instance methods must accept a callback as the last argument. This callback must be called with an error as the first argument and the results as arguments afterward. You must also define the input and output of your remoteable method. Describe the input or arguments of the function by providing an `accepts` array and describe the output by defining a `returns` array. // this method meets the remotable requirements Color.getByName = function (name, callback) { Color.find({where: {name: name}}, function (err, colors) { // if an error occurs callback with the error if(err) { callback(err); } else { callback(null, colors); } }); } // accepts a name of type string Color.getByName.accepts = [ {arg: 'name', type: 'String'} // data definition language ]; // returns an array of type Color Color.getByName.returns = [ {arg: 'colors', type: ['Color']} // data definition language ]; **Note:** any types included in `accepts`/`returns` must be native JavaScript types or Model classes. ### Working with Models The following assumes you have access to an instance of a `Model` class. // define a model var Color = app.define('color'); // create an instance var color = new Color({name: red}); #### myModel.save([options], [callback]) **Remoteable** Save the model using its configured data source. var color = new Color(); color.name = 'green'; // fire and forget color.save(); // callback color.save(function(err, color) { if(err) { console.log(err); // validation or other error } else { console.log(color); // updated with id } }); #### myModel.destroy([callback]) **Remoteable** Delete the instance using attached data source. Invoke callback when ready. var color = Color.create({id: 10}); color.destroy(function(err) { if(err) { console.log(err); // could not destroy } else { console.log('model has been destroyed!'); } }); #### MyModel.all() #### MyModel.find() #### MyModel.count() ### Model Relationships ## Config ### Options #### namespace A table, collection, url, or other namespace. #### properties An array of properties describing the model's schema. "properties": [ { "name": "title", "type": "string" }, { "name": "done", "type": "boolean" }, { "name": "order", "type": "number" } ] } ### Dependencies #### data source The name of a data source [data-source](../data-source) for persisting data.