!CHAPTER Details on FoxxModel The model doesn't know anything about the database. It is just a representation of the data as an JavaScript object. You can add and overwrite the methods of the prototype in your model prototype via the object you give to extend. In your model file, export the model as **model**. ```js var Foxx = require("@arangodb/foxx"); class TodoModel extends Foxx.Model { // ... } exports.model = TodoModel; ``` A Foxx Model can be initialized with an object of attributes and their values. There's also the possibility of annotation: If you extend the model with a **schema** property, the model's attributes will be validated against it. You can define attributes in the schema using the bundled **joi** library. For more information on the syntax see [the official joi documentation](https://github.com/spumko/joi). ```js var Foxx = require("@arangodb/foxx"); var joi = require("joi"); class PersonModel extends Foxx.Model { // ... } PersonModel.prototype.schema = { name: joi.string().required(), age: joi.number().integer(), active: joi.boolean().default(true) }; exports.model = PersonModel; ``` You can also use `joi.object` schemas directly: ```js class PersonModel extends Foxx.Model { // ... } PersonModel.prototype.schema = joi.object().keys({ name: joi.string().required(), age: joi.number().integer(), active: joi.boolean().default(true) }); ``` This has two effects: On the one hand it provides documentation. If you annotated your model, you can use it in the **bodyParam** method for documentation. On the other hand it will influence the behavior of the constructor: If you provide an object to the constructor, it will validate its attributes and set the special **errors** property. This is especially useful if you want to to initialize the Model from user input. On the other hand it will set the default value for all attributes that have not been set by hand. An example: ```js var person = new PersonModel({ name: "Pete", admin: true }); person.attributes // => { name: "Pete", admin: true, active: true } person.errors // => {admin: [ValidationError: value is not allowed]} ``` The following events are emitted by a model: - beforeCreate - afterCreate - beforeSave - afterSave - beforeUpdate - afterUpdate - beforeRemove - afterRemove Equivalent events will also be emitted by the repository handling the model. Model lifecycle: ```js var person = new PersonModel(); person.on('beforeCreate', function() { var model = this; model.fancyMethod(); // Do something fancy with the model }); var people = new Repository(appContext.collection("people"), { model: PersonModel }); people.save(person); // beforeCreate() // beforeSave() // The model is created at db // afterSave() // afterCreate() people.update(person, data); // beforeUpdate(data) // beforeSave(data) // The model is updated at db // afterSave(data) // afterUpdate(data) people.remove(person); // beforeRemove() // The model is deleted at db // afterRemove() ``` !SUBSECTION Extend `FoxxModel#extend(instanceProperties, classProperties)` Extend the Model prototype to add or overwrite methods. The first object contains the properties to be defined on the instance, the second object those to be defined on the prototype. !SUBSECTION Initialize `new FoxxModel(data)` If you initialize a model, you can give it initial *data* as an object. **Examples** ```js instance = new Model({ a: 1 }); ``` !SUBSECTION Get `FoxxModel#get(name)` Get the value of an attribute **Examples** ```js instance = new Model({ a: 1 }); instance.get("a"); ``` !SUBSECTION Set `FoxxModel#set(name, value)` Set the value of an attribute or multiple attributes at once **Examples** ```js instance = new Model({ a: 1 }); instance.set("a", 2); instance.set({ b: 2 }); ``` !SUBSECTION Has `FoxxModel#has(name)` Returns true if the attribute is set to a non-null or non-undefined value. **Examples** ```js instance = new Model({ a: 1 }); instance.has("a"); //=> true instance.has("b"); //=> false ``` !SUBSECTION isValid `model.isValid` The *isValid* flag indicates whether the model's state is currently valid. If the model does not have a schema, it will always be considered valid. !SUBSECTION Errors `model.errors` The *errors* property maps the names of any invalid attributes to their corresponding validation error. !SUBSECTION Attributes `model.attributes` The *attributes* property is the internal hash containing the model's state. !SUBSECTION forDB `FoxxModel#forDB()` Return a copy of the model which can be saved into ArangoDB !SUBSECTION forClient `FoxxModel#forClient()` Return a copy of the model which you can send to the client.