Õpetus: kuidas kirjutada mudeleid Fluent abil

See õpetus näitab teile, kuidas rakendada lihtsat kasutajamudelit, talletada teda andmebaasi, viia ta andmebaasist tagasi ja edastada vaadetele.

Selle õpetuse tulemuse leiate githubist siit

See õpetus on lehe Leaf kasutamise loomulik jätk. Võite minna selle õppematerjali juurde kõigepealt ja tulla hiljem tagasi või olla mässaja, jätta see vahele ja lugeda

Indeks

1. Looge uus projekt
2. Genereerige projekt Xcode
3. Seadistage oma projekt SQLite'i andmebaasi kasutamiseks
4. Looge oma esimene mudel
5. Rakendage kõigi kasutajate loetlemiseks GET-marsruut
6. Asynci selgitamine
7. Mis on F .. ülim
8. Looge vaade
9. Kasutaja salvestamiseks rakendage POST-marsruut
10. Kuhu siit edasi minna

1. Looge uus projekt

Uue projekti loomisel kasutame mallina eelnimetatud õpetuse tulemusi:

vapor new projectName --template = vaporberlin / minu-kõige-lehe-mall

2. Genereerige projekt Xcode

Enne Xcode-projekti genereerimist peaksime lisama andmebaasi pakkuja. Neid on iga andmebaasi jaoks igaüks. ORM Fluentis sooja saamiseks kasutame aga mälu andmebaasis. Seetõttu lisame oma paketi.swifti sõltuvusena Fluent-SQLite:

// swift-tools-version: 4.0
impordi pakettkirjeldus
lase pack = pakett (
  nimi: "projectName", // muudetud
  sõltuvused: [
    .pakend (URL: "https://github.com/vapor/vapor.git", alates: "3.0.0"),
    .pakend (URL: "https://github.com/vapor/leaf.git", alates: "3.0.0-rc"),
   .pakk (URL: "https://github.com/vapor/fluent-sqlite.git", pärit: "3.0.0-rc") // lisatud
  ],
  eesmärgid: [
    .target (nimi: "App", sõltuvused: ["Vapor", "Leaf", "FluentSQLite"]), // lisatud
    .target (nimi: "Run", sõltuvused: ["App"]),
    .testTarget (nimi: "AppTests", sõltuvused: ["App"]),
  ]
)

Nüüd terminalis juurkataloogi projektiNimi / käivitage:

aurude värskendus - ei

Sõltuvuse otsimine, Xcode'i projekti genereerimine ja teie jaoks avamine võib võtta natuke aega. Kui see on valmis, peaks teil olema selline projekti struktuur:

projektiNimi /
├── Pakett.swift
├── Allikad /
│ ├── Rakendus /
├── │ ├── rakendus.swift
├── │ ├── boot.swift
├── │ ├── konfigureerimine.swift
└── │ └── marsruudid
│ └── Käivita /
│ └── main.swift
├── Testid /
├── Ressursid /
├── avalik /
├── Sõltuvused /
└── Tooted /
Kui näete cmd + r korral viga, mis sisaldab märget „CNIOOpenSSL”, puudub teil sõltuvus. Lihtsalt käivitage uuendus aur ja hakake projekti uuesti genereerima

3. Seadistage oma projekt SQLite'i andmebaasi kasutamiseks

Meie esimene samm on lisada FluentSQLiteProvider meie configure.swift:

import aur
importleht
import FluentSQLite // lisatud
avaliku funktsiooni seadistamine (
  _ config: inout Config,
  _ env: inout Environment,
  _ teenused: inout teenused
) viskab {
  // Registreeri marsruuterid marsruuterisse
  lase ruuteril = EngineRouter.default ()
  proovida marsruute (ruuter)
  teenused.register (ruuter, näiteks: ruuteri ise)
  lase leafProvider = LeafProvider ()
  proovige teenuseid.register (leafProvider)
  proovige teenuseid.register (FluentSQLiteProvider ()) // lisatud
  config.prefer (LeafRenderer.self, kasutaja jaoks: ViewRenderer.self)
}

Järgmisena algatame andmebaasiteenuse, lisame sellele SQLiteDatabase ja registreerime selle andmebaasiteenuse:

import aur
importleht
importige FluentSQLite
avaliku funktsiooni seadistamine (
  _ config: inout Config,
  _ env: inout Environment,
  _ teenused: inout teenused
) viskab {
  // Registreeri marsruuterid marsruuterisse
  lase ruuteril = EngineRouter.default ()
  proovida marsruute (ruuter)
  teenused.register (ruuter, näiteks: ruuteri ise)
  lase leafProvider = LeafProvider ()
  proovige teenuseid.register (leafProvider)
  proovige teenuseid.register (FluentSQLiteProvider ())
  config.prefer (LeafRenderer.self, kasutaja jaoks: ViewRenderer.self)
  var andmebaasid = DatabasesConfig ()
  proovige andmebaasid.add (andmebaas: SQLiteDatabase (salvestusruum: .mälu), kui: .sqlite)
  teenused.register (andmebaasid)
}

Lõpuks algatame ja registreerime rändeteenuse, mida kasutame hiljem, et oma mudelit oma andmebaasi tutvustada. Praegu lisage järgmine teave:

import aur
importleht
importige FluentSQLite
avaliku funktsiooni seadistamine (
  _ config: inout Config,
  _ env: inout Environment,
  _ teenused: inout teenused
) viskab {
  // Registreeri marsruuterid marsruuterisse
  lase ruuteril = EngineRouter.default ()
  proovida marsruute (ruuter)
  teenused.register (ruuter, näiteks: ruuteri ise)
  lase leafProvider = LeafProvider ()
  proovige teenuseid.register (leafProvider)
  proovige teenuseid.register (FluentSQLiteProvider ())
  config.prefer (LeafRenderer.self, kasutaja jaoks: ViewRenderer.self)
  var andmebaasid = DatabaseConfig ()
  proovige andmebaasid.add (andmebaas: SQLiteDatabase (salvestusruum: .mälu), kui: .sqlite)
  teenused.register (andmebaasid)
  var migrations = MigrationConfig ()
  teenused.register (ränded)
}

4. Looge oma esimene mudel

Looge kataloog allikates / rakenduses / ja pange sellele nimeks Models / ning looge selles uues kataloogis uus kiirfail nimega User.swift

MÄRKUS. Kasutasin terminali, mis käivitas mkdir Allikad / Rakendus / Mudelid / ja puudutasite Allikad / Rakendus / Mudelid / Kasutaja.swift

Võimalik, et peate Xcode'i projekti uuesti genereerima aururikoodiga -y, et Xcode saaks teie uut kataloogi näha.

Jaotises Models / User.swift sisaldage järgmist koodi:

importige FluentSQLite
import aur
lõpuklassi kasutaja: SQLiteModel {
  var id: Int?
  var kasutajanimi: String
  init (id: Int? = null, kasutajanimi: String) {
    self.id = id
    self.username = kasutajanimi
  }
}
laiend Kasutaja: sisu {}
laiendi kasutaja: migratsioon {}

Pidasin seda ülilihtsaks, et saaksime aru, mis siin toimub. Kooskõlas SQLiteModeliga peame määratlema valikulise muutuja nimega id, mille tüüp on int. See on valikuline lihtsalt seetõttu, et kui algatame uue kasutaja tema andmebaasi talletamiseks, pole meie ülesanne anda talle sel hetkel ID. Pärast andmebaasi talletamist saab ta ID.

Vastavus sisule võimaldab seda, et meie kasutaja saab Covablei abil teisendada näiteks JSON-iks, kui me suunaksime teda marsruudile tagasi. Või saab ta teisendada TemplateData-ks, mida kasutatakse lehevaates. Ja tänu Codable'ile juhtub see automaatselt. Vaja on migratsioonile vastavust, nii et Fluent saaks kasutada Covablei parima võimaliku andmebaasi tabeli skeemi loomiseks ja ka siis, et saaksime selle oma migreerimisteenusele lisada oma configure.swift:

import aur
importleht
importige FluentSQLite
avaliku funktsiooni seadistamine (
  _ config: inout Config,
  _ env: inout Environment,
  _ teenused: inout teenused
) viskab {
  // Registreeri marsruuterid marsruuterisse
  lase ruuteril = EngineRouter.default ()
  proovida marsruute (ruuter)
  teenused.register (ruuter, näiteks: ruuteri ise)
  lase leafProvider = LeafProvider ()
  proovige teenuseid.register (leafProvider)
  proovige teenuseid.register (FluentSQLiteProvider ())
  config.prefer (LeafRenderer.self, kasutaja jaoks: ViewRenderer.self)
  var andmebaasid = DatabaseConfig ()
  proovige andmebaasid.add (andmebaas: SQLiteDatabase (salvestusruum: .mälu), kui: .sqlite)
  teenused.register (andmebaasid)
  var migrations = MigrationConfig ()
  migrations.add (mudel: User.self, andmebaas: .sqlite)
  teenused.register (ränded)
}

Kui nüüd vajutate cmd + r või jooksete, peaks kõik olema hästi.

Märkus. Enne rakenduse käivitamist valige kindlasti nupu kõrval skeem

5. Rakendage kõigi kasutajate loetlemiseks GET-marsruut

Jah, meil pole veel ühtegi andmebaasi kasutajat, kuid loome ja salvestame kasutajaid enda rakendatava vormi abil. Nii et minge nüüd marsruudile marsruutid.swift ja kustutage failist kõik, nii et see näeb välja selline:

import aur
importleht
avalikud funktsionaalsed marsruudid (_ ruuter: ruuter) viskab {
  // siin pole midagi
}

Määrake hankimismarsruut URL-i kasutajate poolt, kes tõmbab kõik kasutajad andmebaasist, ja sisestage nad vaatesse:

import aur
importleht
avalikud funktsionaalsed marsruudid (_ ruuter: ruuter) viskab {
  
  ruuter.get ("kasutajad") {req -> Future  in
    return User.query (sisse: req) .all (). flatMap {kasutajad sisse
      lase data = ["kasutajate nimekiri": kasutajad]
      tagasi proovida req.view (). render ("kasutajavaade", andmed)
    }
  }
}

Vau. Siin toimub palju. Kuid ärge muretsege, see on palju lihtsam, kui tundub, ja tunnete end suurepäraselt, kui loete veel edasi ja mõistate seda musta maagiat

VAPOR 3 on seotud tulevikutega. Ja see tuleneb sellest, et ta on nüüd Async.

6. Asynci selgitamine

Olgem näiteks elust. Kui Vapor 2-s ta sõbranna käskis poisil osta talle pehme jää ja sõõriku. Ta läheks jäävagunisse, telliks jää ja ootaks, kuni see on valmis. Siis ta jätkaks ja läheks sõõrikupoodi, ostaks ühe ja läheks mõlemaga tagasi oma sõbranna juurde.

Vapor 3 abil läheks see poiss jäävagunisse, telliks jääd ja jää valmistamise ajal läheks ta sõõrikupoodi ja ostaks sõõriku. Ta tuleb jäävagunisse tagasi, kui jää on valmis, saab selle ja läheb mõlemaga tagasi oma sõbranna juurde.

Aur 2: Jääkäsk blokeeris poisi lõpuni, kuni ta saab edasi minna.
Vapor 3: Poiss töötab mitteblokeerivalt ja kasutab oma ooteaega muudeks ülesanneteks.

7. Mis on F .. ülim

Saame aru, mis toimub ja miks. Me kasutame andmebaasi pärimiseks oma kasutajaklassi. Ja saate seda lugeda nagu päringu täitmine meie päringu tagaküljel. Mõelge taotlusele kui poisile. See, kes teeb meie heaks töö ära. Tööline.

Olgu, meil pole kasutajarühma, vaid kasutajate arvu tulevikku: tulevik <[kasutajad]>. Ja ausalt. See selleks. Ja mida ma mõtlen selle all: selles pole midagi väljamõeldud ega erilist. See on lihtsalt see. See on lihtsalt tuleviku poolt pakitud. Ainus asi, mis meid huvitab, on see, kuidas emade nimel saame oma andmed tulevikus välja, kui tahame sellega töötada nii, nagu oleme harjunud

Seal mängitakse kaarti või flatMap-i.

Valime kaardi, kui kõne põhiosa tagastab tulevikuväärtuse.

someFuture.map {andmed
  tagastatav väärtus
}

Ja kui keha tõstab tulevase väärtuse, kutsume seda flatMapiks.

someFuture.flatMap {andmed
  tagasi tulevik 
}

On ainult see lihtne reegel. Kuna peate igas kaardifunktsioonis midagi tagastama, ütleb just see, kas kasutate flatMap-i või kaarti. Reegel on järgmine: kui see miski on tulevik, kasutate flatMap-i ja kui see on “tavaline” teave, siis ei kasuta te tulevikku.

Seega tahame oma marsruudil pääseda juurde kasutajate hulgale, et seda meie vaatesse edastada. Seega vajame ühte mõlemast kaardifunktsioonist. Ja kuna me tagastame kõik, mida render () funktsioon tagastab. Ja kui me sellel + klõpsate, näeme, et see on tulevik , oleme õppinud: kui tagastame tuleviku, kasutage flatMap-i.

Ja see on kõik, mida me siin teeme. Ärge muretsege, kui see tundub imelik ja uus ning pole nii intuitiivne. Ja te ei tunne, nagu teaksite, mida ja kuidas kasutada. See on see, mille nimel ma siin (loodetavasti) olen . Jälgige õpetusi ja küsige minult või Discordi kogukonnalt igasugu küsimusi ja uskuge mind, see klõpsab! Ausalt, ma ei olnud kindel, et see minu jaoks klõpsab, kuni ta seda tegi. Andke aega !

8. Looge vaade

Ressursside / vaadete alt kustutage kõik seal leiduvad failid (welcome.leaf ja whoami.leaf) ja looge uus fail nimega userview.leaf ja lisage:



  
     mudel 
    
  
  
    

kasutajate loend

    
      
                   
                           Loo                        
      
    
    #for (kasutaja kasutajaloendis) {
      

        # (user.username)       

    }   

Olen siin märkinud huvitavad asjad. Märgendiga lisan lihtsalt alglaadimise, mis on css-raamistik, mis muudab meie vaate natuke kenamaks.

Sildiga

määratleme, mis juhtub vormi esitamisel, mis tulistab kasutajatele / meetodipostitusele. Viime selle postitee teisele.

on meie sisestusväli, kuhu kirjutada uus kasutajanimi ja siin on nimi = “kasutajanimi” ülitähtis, sest “kasutajanimi” on võti, kuhu meie tekst ühendatakse. Saate aru, mida ma mõtlen, kui kirjutame oma postitee.

Silmus #for () on lehespetsiifiline silt, kus me iteratsioonime varem kasutajaloendist üle, nagu me kasutame vaadet [“userlist”:…] ja numbriga # (user.username) pääseme oma objektidele juurde nagu kiiresti.

Kui teil on cmd + r või käivitate projekti ja käivitate oma saidi aadressil / kasutajad, näete päist, sisestusvälja ja nuppu. Ja see on täiesti korras. Kasutajate loend ilmub kohe, kui oleme mõne loonud. Teeme ära !

9. Kasutaja salvestamiseks rakendage POST-marsruut

Lisage meie marsruutidele.swift järgmine kood:

import aur
importleht
avalikud funktsionaalsed marsruudid (_ ruuter: ruuter) viskab {
  ruuter.get ("kasutajad") {req -> Future  in
    ...
  }
  ruuter.post ("kasutajad") {req -> Future  in
    tagasi proovida req.content.decode (Kasutaja ise) .flatMap {kasutaja
      return user.save (sisse: req) .map {_ sisse
        tagastama req.redirect (kasutajatele)
      }
    }
  }
}

Kui edastame oma vormi vaatena, vajutades nuppu Esita, saadab see sisendvälja andmevormi-url-kodeeritud kasutajale marsruudil postitusena nagu:

kasutajanimi = MartinLasek

Kuna meie kasutajamudel koosneb ainult ühest vara kasutajanimi ja vastab protokolli sisule, siis on meil võimalik dekodeerida vormi poolt saadetud sisu meie kasutaja esinemisjuhuks. Võite proovida, mis juhtub, kui lisate meie kasutajaklassi mõne muu atribuudi, näiteks Int tüüpi vanus, uuesti projekti käivitada ja proovida vormi uuesti esitada. See annab teile teada, et ta ei leidnud tee vanuses rändajat. Kuna meie vorm ei saada kasutajanime kõrval vanust = 23.

Kuna dekodeerimine tagastab kasutaja eksemplari tuleviku, peame sellele juurdepääsu saamiseks kasutama ühte funktsiooni map / flatMap. Nüüd väike kõrvalmärkus. Mõlemad funktsioonid tervikuna annavad tuleviku. Ma ei räägi nende funktsioonide põhiosast. Ma räägin kogu kõnest. See on oluline, kuna see selgitab, miks kutsume dekodeerimiseks flatMap-i.

Taas kasutatakse flatMap-i, kui keha annab meile tuleviku. Ja saime just teada, et flatMap ja kaart tervikuna annavad alati tuleviku. Näete, et tagastame kasutaja.save (sisse: req) .map {…} nüüd, kuna see tervik tervikuna annab tuleviku, me teame, et peame FlatMapit kasutama kohe.

Järgmine on lihtne, kuna ümbersuunamine ei tagasta tulevikku, seetõttu kasutame siin kaarti ette

Tulevasele väärtusele juurdepääsu saamiseks vajate kas kaarti või flatMap-i. Kui teie tagastatav väärtus kaardifunktsioonis ei ole tulevik, kasutate kaarti muidu flatMap.

Kui teete nüüd cmd + r või käivitate oma projekti ja käivitate oma saidi oma brauseris, saate luua uusi kasutajaid ja näha seda tehes üha kasvavat loendit

MÄRKUS. Kuna me kasutame mälu andmebaasis, lähevad kõik andmed pärast taaskäivitamist kaduma

10. Kuhu siit edasi minna

Kõigi Githubi näidisprojektide õpetuste loendi leiate siit:
https://github.com/vaporberlin/vaporschool

Mul on tõesti hea meel, et lugesite minu artiklit! Kui teil on mingeid ettepanekuid või parandusi, andke mulle sellest teada! Mulle meeldiks teid kuulda!

Twitter / Github / Instagram