✎ Edit on GitHub

# Model

`Model` is the base protocol for any of your application's models, especially those you want to persist.

> `Model` is only available in Vapor, the Fluent equivalent is `Entity`

## Example

Let's create a simple `User` model.

    final class User {
        var name: String

        init(name: String) {
            self.name = name
        }
    }

The first step to conforming to `Model` is to import Vapor and Fluent.

    import Vapor
    import Fluent

Then add the conformance to your class.

    final class User: Model {
        ...
    }

The compiler will inform you that some methods need to be implemented to conform.

### ID

The first required property is an identifier. This property will contain the identifier when the model is fetched from the database. If it is `nil`, it will be set when the model is saved.

    final class User: Model {
        var id: Node?
        ...
    }

### Node Initializable

The next requirement is a way to create the model from the persisted data. Model uses `NodeInitializable` to achieve this.

    final class User: Model {
        init(node: Node, in context: Context) throws {
            id = try node.extract("id")
            name = try node.extract("name")
        }
        ...
    }

The keys `id` and `name` are what we expect the columns or fields in the database to be named. The `extract` call is marked with a `try` because it will throw an error if the value is not present or is the wrong type.

### Node Representable

Now that we have covered initializing the model, we need to show how to save it back into the database. Model uses `NodeRepresentable` to achieve this.

    final class User: Model {
        func makeNode(context: Context) throws -> Node {
            return try Node(node: [
                "id": id,
                "name": name
            ])
        }
        ...
    }

When a `User` is saved, the `makeNode()` method will be called and the resulting `Node` will be saved to the database. The keys `id` and `name` are what we expect the columns or fields in the database to be named.

> In most of the cases you do not need to be concerned about `context` argument of the `makeNode(context:)` method. It’s a part of the protocol that allows extensibility in more advanced or specific scenarios.

## Preparations

Some databases, like MySQL, need to be prepared for a new schema. In MySQL, this means creating a new table. Preparations are also equatable to migrations, as they can be used to alter schemas after they've already been created.

### Prepare

Let's assume we are using a SQL database. To prepare the database for our `User` class, we need to create a table. If you are using a database like Mongo, you can leave this method unimplemented.

    final class User {
        static func prepare(_ database: Database) throws {
            try database.create("users") { users in
                users.id()
                users.string("name")
            }
        }
        ...
    }

Here we create a table named `users` that has an identifier field and a string field with the key `name`. This matches both our `init(node: Node)` and `makeNode() -> Node` methods.

### Revert

An optional preparation reversion can be created. This will be run if `vapor run prepare --revert` is called.

    final class User {
        static func revert(_ database: Database) throws {
            try database.delete("users")
        }
        ...
    }

Here we are deleting the table named `users`.

### Preparations as Migrations

If you want to add a field to your table after you've already created the initial schema, you can create a struct or class that conforms to `Preparation` like so:

    struct AddFooToBar: Preparation {
        static func prepare(_ database: Database) throws {
            try database.modify("bars", closure: { bar in
                bar.string("foo", length: 150, optional: false, unique: false, default: nil)
            })
        }

        static func revert(_ database: Database) throws {

        }
    }

Then, in your Droplet setup, add this line: `drop.preparations.append(AddFooToBar.self)`

### Droplet

To run these prepations when the applications boots, you must add the Model to the `Droplet`.

    let drop = Droplet()

    drop.preparations.append(User.self)

> Note: Preparations must be appended before the Droplet is run.

## Full Model

This is what our final `User` model looks like:

    import Vapor
    import Fluent

    final class User: Model {
        var id: Node?
        var name: String

        init(name: String) {
            self.name = name
        }

        init(node: Node, in context: Context) throws {
            id = try node.extract("id")
            name = try node.extract("name")
        }

        func makeNode(context: Context) throws -> Node {
            return try Node(node: [
                "id": id,
                "name": name
            ])
        }

        static func prepare(_ database: Database) throws {
            try database.create("users") { users in
                users.id()
                users.string("name")
            }
        }

        static func revert(_ database: Database) throws {
            try database.delete("users")
        }
    }

## Interacting

Now that `User` conforms to `Model`, it has a plethora of new methods like `find()`, `query()`, `makeJSON()` and more.

### Fetch

Models can be fetched by their database identifier.

    let user = try User.find(42)

### Save

Newly created models can be saved to the database.

    var user = User(name: "Vapor")
    try user.save()
    print(user.id) // prints the new id

### Delete

Persisted models with identifiers can be deleted.

    try user.delete()

## Model vs. Entity

Model has a couple of extra conformances that a pure Fluent entity doesn't have.

    public protocol Model: Entity, JSONRepresentable, StringInitializable, ResponseRepresentable {}

As can be seen in the protocol, Vapor models can automatically convert to `JSON`, `Response`, and even be used in type-safe routing.

## Options

Change the table/collection name

    static var entity = "new_name"