Back-End

5 set, 2018

Vapor 3 Postgres e OneModel

Publicidade

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.

Fique à vontade e crie como preferir.

Espero que tenham gostado e em breve trarei novos artigos sobre o Vapor!