O objetivo aqui, é criar uma api com reaproveitamento de modelo de dados para uso em aplicativo nativo.
Instalando o Vapor
Siga as instruções do site oficial: https://docs.vapor.codes/3.0/install/macos/
Após instalado e com o XCode aberto, vamos instalar o Fluent para o PostreSQL, que será o responsável por toda a comunicação de model / vapor com nosso banco de dados.
Adicione o pacote no arquivo Package.swift:
dependencies: [ // ? A server-side Swift web framework. .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"), .package(url: "https://github.com/vapor/fluent-sqlite.git", from: "3.0.0") .package(url: "https://github.com/vapor/fluent-postgresql.git", from: "1.0.0"), ], targets: [ .target(name: "App", dependencies: ["FluentSQLite", "FluentPostgreSQL", "Vapor"]),
Após adicionar as linhas e dependências, execute novamente o comando a seguir para que sejam instaladas as dependências no projeto.:
$ vapor xcode
Faça isso sempre que adicionar e ou remover alguma dependência. Feito isso, vamos começar as configurações:
Configurações de Serviços, IP e porta
IP e Porta
//Configure IP And Port let serverConfiure = NIOServerConfig.default(hostname: "0.0.0.0", port: 8080) services.register(serverConfiure)
Fluent PostgreSQL DataBase
/// Configure a PostgreSQL database var databases = DatabasesConfig() let databaseConfig = PostgreSQLDatabaseConfig(hostname: "localhost", username: "michel", database: "todoDemo1") let dataBase = PostgreSQLDatabase(config: databaseConfig) databases.add(database: dataBase, as: .psql) services.register(databases)
Migrations
/// Configure migrations var migrations = MigrationConfig() migrations.add(model: Todo.self, database: .psql) //migrations.add(model: Todo.self, database: .psql) services.register(migrations)
Configurando Model: Sources > App > Models > Todo.Swift
Vamos alterar o model Todo para o seguinte formato, removendo o import do FluentSQLite e também o protocolo SQLiteModel, substituindo por Codable. Adicionaremos um atributo/campo do tipo Bool:
import Foundation /// A single entry of a Todo list. final class Todo: Codable { /// The unique identifier for this `Todo`. var id: Int? /// A title describing what this `Todo` entails. var title: String /// A flag describing if this `Todo` is done. var done: Bool? /// Creates a new `Todo`. init(id: Int? = nil, title: String, done: Bool? = false) { self.id = id self.title = title self.done = false } }
Agora recortaremos as seguintes linhas que estão abaixo da class Todo:
/// Allows `Todo` to be used as a dynamic migration. extension Todo: Migration { } /// Allows `Todo` to be encoded to and decoded from HTTP messages. extension Todo: Content { } /// Allows `Todo` to be used as a dynamic parameter in route definitions. extension Todo: Parameter { }
Agora abra o arquivo: Sources > App > Controllers > TodoController.Swift
Logo abaixo do import Vapor, cole o código que copiamos do arquivo Todo.swift.
Vamos aproveitar e importar também a Lib FluentPostgreSQL e adicionar a Extension para o mesmo.
extension Todo: PostgreSQLModel { }
Nosso arquivo após os ajustes devem ficar assim:
import Vapor import FluentPostgreSQL extension Todo: PostgreSQLModel { } /// Allows `Todo` to be used as a dynamic migration. extension Todo: Migration { } /// Allows `Todo` to be encoded to and decoded from HTTP messages. extension Todo: Content { } /// Allows `Todo` to be used as a dynamic parameter in route definitions. extension Todo: Parameter { } /// Controls basic CRUD operations on `Todo`s. final class TodoController { /// Returns a list of all `Todo`s. func index(_ req: Request) throws -> Future<[Todo]> { return Todo.query(on: req).all() } /// Saves a decoded `Todo` to the database. func create(_ req: Request) throws -> Future<Todo> { return try req.content.decode(Todo.self).flatMap { todo in return todo.save(on: req) } } /// Deletes a parameterized `Todo`. func delete(_ req: Request) throws -> Future<HTTPStatus> { return try req.parameters.next(Todo.self).flatMap { todo in return todo.delete(on: req) }.transform(to: .ok) } }
Fizemos esses ajustes para isolarmos o arquivo de model Todo para usá-lo tanto no Vapor, quanto em um projeto de app sem se preocupar com dependências.
Neste momento já podemos rodar o projeto e ver o banco criado com o Target Run selecionado, aperte “Command” + “R” para rodar o projeto.
Se tudo deu certo você deve ter a seguinte saída no console do XCode:
E se você abrir seu gerenciador de banco, terá o banco criado também (eu uso o pgAdmin).
Podemos fazer um commit de nossas alterações e partir para o próximo branch.
Testando API com Postman
Você pode facilmente testar a api com o Aplicativo Postman:
Se fizermos um get no mesmo endereço já teremos a listagem com as Todos criadas. Se acessarmos no navegador o endereço http://localhost:8080/todos, também teremos acesso às todos criadas.
Criando um App de Todo e Reaproveitando o Model
Primeiro precisamos adicionar um novo Target no projeto:
1. Selecione o Projeto e clique no ícone “+“, conforme na imagem abaixo:
2. Selecione Single View App:
3. Preencha os campos conforme preferir e dê ok:
Pronto, você tem um novo target criado. Agora precisamos fazer com que o Model seja visto por nosso novo target.
Para isso selecione o arquivo de model e na coluna de Utilities marque o target do App, conforme imagem abaixo:
Agora o Model Todo já está visivel para o Target do App.
Não vou entrar no melhor modo de fazer um app de Todo, mas vou deixar o projeto final no GitHub para que vocês vejam o tutorial rodando e criando registros.
- Link do projeto final: https://github.com/micheltlutz/todoCocoaHeads
- Slides disponíveis no link a seguir: https://www.slideshare.net/michelboss/cocoaheads-poa-agosto-18
Fique à vontade e crie como preferir.
Espero que tenham gostado e em breve trarei novos artigos sobre o Vapor!