--- currentMenu: fluent-model --- # 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. ```swift 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. ```swift import Vapor import Fluent ``` Then add the conformance to your class. ```swift 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. ```swift 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. ```swift 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. ```swift 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. ```swift 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. ```swift 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: ```swift 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`. ```swift 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: ```swift 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. ```swift let user = try User.find(42) ``` ### Save Newly created models can be saved to the database. ```swift var user = User(name: "Vapor") try user.save() print(user.id) // prints the new id ``` ### Delete Persisted models with identifiers can be deleted. ```swift try user.delete() ``` ## Model vs. Entity Model has a couple of extra conformances that a pure Fluent entity doesn't have. ```swift 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 ```swift static var entity = "new_name" ```