255 lines
7.0 KiB
Markdown
255 lines
7.0 KiB
Markdown
# 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. |