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.
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
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.