mirror of https://github.com/vapor/docs.git
1949 lines
54 KiB
HTML
1949 lines
54 KiB
HTML
|
|
|
|
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="en" class="no-js">
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
|
|
|
|
|
|
|
|
<meta name="lang:clipboard.copy" content="Copy to clipboard">
|
|
|
|
<meta name="lang:clipboard.copied" content="Copied to clipboard">
|
|
|
|
<meta name="lang:search.language" content="en">
|
|
|
|
<meta name="lang:search.pipeline.stopwords" content="True">
|
|
|
|
<meta name="lang:search.pipeline.trimmer" content="True">
|
|
|
|
<meta name="lang:search.result.none" content="No matching documents">
|
|
|
|
<meta name="lang:search.result.one" content="1 matching document">
|
|
|
|
<meta name="lang:search.result.other" content="# matching documents">
|
|
|
|
<meta name="lang:search.tokenizer" content="[\s\-]+">
|
|
|
|
<link rel="shortcut icon" href="../../assets/images/favicon.png">
|
|
<meta name="generator" content="mkdocs-0.17.3, mkdocs-material-2.7.0">
|
|
|
|
|
|
|
|
<title>Models - Vapor Docs</title>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../assets/stylesheets/application.78aab2dc.css">
|
|
|
|
<link rel="stylesheet" href="../../assets/stylesheets/application-palette.6079476c.css">
|
|
|
|
|
|
|
|
<script src="../../assets/javascripts/modernizr.1aa3b519.js"></script>
|
|
|
|
|
|
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
|
|
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
|
|
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
|
|
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<body dir="ltr" data-md-color-primary="blue" data-md-color-accent="purple">
|
|
|
|
<svg class="md-svg">
|
|
<defs>
|
|
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
|
|
viewBox="0 0 416 448" id="github">
|
|
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
|
|
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
|
|
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
|
|
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
|
|
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
|
|
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
|
|
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
|
|
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
|
|
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
|
|
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
|
|
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
|
|
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
|
|
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
|
|
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
|
|
99.5z" />
|
|
</svg>
|
|
|
|
</defs>
|
|
</svg>
|
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="drawer">
|
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="search">
|
|
<label class="md-overlay" data-md-component="overlay" for="drawer"></label>
|
|
|
|
<a href="#fluent-models" tabindex="1" class="md-skip">
|
|
Skip to content
|
|
</a>
|
|
|
|
|
|
<header class="md-header" data-md-component="header">
|
|
<nav class="md-header-nav md-grid">
|
|
<div class="md-flex">
|
|
<div class="md-flex__cell md-flex__cell--shrink">
|
|
<a href="../.." title="Vapor Docs" class="md-header-nav__button md-logo">
|
|
|
|
<img src="../../images/droplet-white.svg" width="24" height="24">
|
|
|
|
</a>
|
|
</div>
|
|
<div class="md-flex__cell md-flex__cell--shrink">
|
|
<label class="md-icon md-icon--menu md-header-nav__button" for="drawer"></label>
|
|
</div>
|
|
<div class="md-flex__cell md-flex__cell--stretch">
|
|
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
|
|
|
|
|
|
<span class="md-header-nav__topic">
|
|
Vapor Docs
|
|
</span>
|
|
<span class="md-header-nav__topic">
|
|
Models
|
|
</span>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
<div class="md-flex__cell md-flex__cell--shrink">
|
|
|
|
|
|
<label class="md-icon md-icon--search md-header-nav__button" for="search"></label>
|
|
|
|
<div class="md-search" data-md-component="search" role="dialog">
|
|
<label class="md-search__overlay" for="search"></label>
|
|
<div class="md-search__inner" role="search">
|
|
<form class="md-search__form" name="search">
|
|
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
|
|
<label class="md-icon md-search__icon" for="search"></label>
|
|
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
|
|

|
|
</button>
|
|
</form>
|
|
<div class="md-search__output">
|
|
<div class="md-search__scrollwrap" data-md-scrollfix>
|
|
<div class="md-search-result" data-md-component="result">
|
|
<div class="md-search-result__meta">
|
|
Type to start searching
|
|
</div>
|
|
<ol class="md-search-result__list"></ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
<div class="md-flex__cell md-flex__cell--shrink">
|
|
<div class="md-header-nav__source">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="http://github.com/vapor/vapor/" title="Go to repository" class="md-source" data-md-source="github">
|
|
|
|
<div class="md-source__icon">
|
|
<svg viewBox="0 0 24 24" width="24" height="24">
|
|
<use xlink:href="#github" width="24" height="24"></use>
|
|
</svg>
|
|
</div>
|
|
|
|
<div class="md-source__repository">
|
|
GitHub
|
|
</div>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
|
|
<div class="md-container">
|
|
|
|
|
|
|
|
|
|
<main class="md-main">
|
|
<div class="md-main__inner md-grid" data-md-component="container">
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
<nav class="md-nav md-nav--primary" data-md-level="0">
|
|
<label class="md-nav__title md-nav__title--site" for="drawer">
|
|
<span class="md-nav__button md-logo">
|
|
|
|
<img src="../../images/droplet-white.svg" width="48" height="48">
|
|
|
|
</span>
|
|
Vapor Docs
|
|
</label>
|
|
|
|
<div class="md-nav__source">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="http://github.com/vapor/vapor/" title="Go to repository" class="md-source" data-md-source="github">
|
|
|
|
<div class="md-source__icon">
|
|
<svg viewBox="0 0 24 24" width="24" height="24">
|
|
<use xlink:href="#github" width="24" height="24"></use>
|
|
</svg>
|
|
</div>
|
|
|
|
<div class="md-source__repository">
|
|
GitHub
|
|
</div>
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../.." title="Overview" class="md-nav__link">
|
|
Overview
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-2" type="checkbox" id="nav-2">
|
|
|
|
<label class="md-nav__link" for="nav-2">
|
|
Install
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-2">
|
|
Install
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../install/macos/" title="macOS" class="md-nav__link">
|
|
macOS
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../install/ubuntu/" title="Ubuntu" class="md-nav__link">
|
|
Ubuntu
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-3" type="checkbox" id="nav-3">
|
|
|
|
<label class="md-nav__link" for="nav-3">
|
|
Getting started
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-3">
|
|
Getting started
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/hello-world/" title="Hello, world" class="md-nav__link">
|
|
Hello, world
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/toolbox/" title="Toolbox" class="md-nav__link">
|
|
Toolbox
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/spm/" title="SPM" class="md-nav__link">
|
|
SPM
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/xcode/" title="Xcode" class="md-nav__link">
|
|
Xcode
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/structure/" title="Folder Structure" class="md-nav__link">
|
|
Folder Structure
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/application/" title="Application" class="md-nav__link">
|
|
Application
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/controllers/" title="Controllers" class="md-nav__link">
|
|
Controllers
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/routing/" title="Routing" class="md-nav__link">
|
|
Routing
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/content/" title="Content" class="md-nav__link">
|
|
Content
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/futures/" title="Futures" class="md-nav__link">
|
|
Futures
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/services/" title="Services" class="md-nav__link">
|
|
Services
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../getting-started/cloud/" title="Deployment" class="md-nav__link">
|
|
Deployment
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-4" type="checkbox" id="nav-4">
|
|
|
|
<label class="md-nav__link" for="nav-4">
|
|
Routing
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-4">
|
|
Routing
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../routing/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../routing/parameters/" title="Parameters" class="md-nav__link">
|
|
Parameters
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../routing/route/" title="Route" class="md-nav__link">
|
|
Route
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../routing/router/" title="Router" class="md-nav__link">
|
|
Router
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-5" type="checkbox" id="nav-5" checked>
|
|
|
|
<label class="md-nav__link" for="nav-5">
|
|
Fluent
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-5">
|
|
Fluent
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="toc">
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__link md-nav__link--active" for="toc">
|
|
Models
|
|
</label>
|
|
|
|
<a href="./" title="Models" class="md-nav__link md-nav__link--active">
|
|
Models
|
|
</a>
|
|
|
|
|
|
<nav class="md-nav md-nav--secondary">
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__title" for="toc">Table of contents</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#conformance" title="Conformance" class="md-nav__link">
|
|
Conformance
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#associated-types" title="Associated Types" class="md-nav__link">
|
|
Associated Types
|
|
</a>
|
|
|
|
<nav class="md-nav">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#database" title="Database" class="md-nav__link">
|
|
Database
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#id" title="ID" class="md-nav__link">
|
|
ID
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#properties" title="Properties" class="md-nav__link">
|
|
Properties
|
|
</a>
|
|
|
|
<nav class="md-nav">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#name" title="Name" class="md-nav__link">
|
|
Name
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#entity" title="Entity" class="md-nav__link">
|
|
Entity
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#id-key" title="ID Key" class="md-nav__link">
|
|
ID Key
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#lifecycle" title="Lifecycle" class="md-nav__link">
|
|
Lifecycle
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#crud" title="CRUD" class="md-nav__link">
|
|
CRUD
|
|
</a>
|
|
|
|
<nav class="md-nav">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#create" title="Create" class="md-nav__link">
|
|
Create
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#read" title="Read" class="md-nav__link">
|
|
Read
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#update" title="Update" class="md-nav__link">
|
|
Update
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#delete" title="Delete" class="md-nav__link">
|
|
Delete
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#methods" title="Methods" class="md-nav__link">
|
|
Methods
|
|
</a>
|
|
|
|
<nav class="md-nav">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#require-id" title="Require ID" class="md-nav__link">
|
|
Require ID
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../migrations/" title="Migrations" class="md-nav__link">
|
|
Migrations
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../querying/" title="Querying" class="md-nav__link">
|
|
Querying
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../query-builder/" title="Query Builder" class="md-nav__link">
|
|
Query Builder
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../schema-builder/" title="Schema Builder" class="md-nav__link">
|
|
Schema Builder
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../relations/" title="Relations" class="md-nav__link">
|
|
Relations
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../pivot/" title="Pivot" class="md-nav__link">
|
|
Pivot
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../transaction/" title="Transaction" class="md-nav__link">
|
|
Transaction
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../database/" title="Database" class="md-nav__link">
|
|
Database
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-6" type="checkbox" id="nav-6">
|
|
|
|
<label class="md-nav__link" for="nav-6">
|
|
PostgreSQL
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-6">
|
|
PostgreSQL
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../postgresql/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../postgresql/fluent/" title="Fluent PostgreSQL" class="md-nav__link">
|
|
Fluent PostgreSQL
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../postgresql/core/" title="PostgreSQL Core" class="md-nav__link">
|
|
PostgreSQL Core
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-7" type="checkbox" id="nav-7">
|
|
|
|
<label class="md-nav__link" for="nav-7">
|
|
MySQL
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-7">
|
|
MySQL
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../mysql/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../mysql/fluent/" title="Fluent MySQL" class="md-nav__link">
|
|
Fluent MySQL
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../mysql/core/" title="MySQL Core" class="md-nav__link">
|
|
MySQL Core
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-8" type="checkbox" id="nav-8">
|
|
|
|
<label class="md-nav__link" for="nav-8">
|
|
SQLite
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-8">
|
|
SQLite
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../sqlite/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../sqlite/fluent/" title="Fluent SQLite" class="md-nav__link">
|
|
Fluent SQLite
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../sqlite/core/" title="SQLite Core" class="md-nav__link">
|
|
SQLite Core
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
|
|
|
|
<label class="md-nav__link" for="nav-9">
|
|
Leaf
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-9">
|
|
Leaf
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../leaf/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../leaf/basics/" title="Basics" class="md-nav__link">
|
|
Basics
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../leaf/custom-tags/" title="Custom tags" class="md-nav__link">
|
|
Custom tags
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-10" type="checkbox" id="nav-10">
|
|
|
|
<label class="md-nav__link" for="nav-10">
|
|
Redis
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-10">
|
|
Redis
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../redis/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../redis/basics/" title="Basics" class="md-nav__link">
|
|
Basics
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../redis/custom-commands/" title="Custom commands" class="md-nav__link">
|
|
Custom commands
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../redis/pub-sub/" title="Publish and Subscribe" class="md-nav__link">
|
|
Publish and Subscribe
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../redis/pipeline/" title="Pipeline" class="md-nav__link">
|
|
Pipeline
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-11" type="checkbox" id="nav-11">
|
|
|
|
<label class="md-nav__link" for="nav-11">
|
|
WebSocket
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-11">
|
|
WebSocket
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../websocket/websocket/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-12" type="checkbox" id="nav-12">
|
|
|
|
<label class="md-nav__link" for="nav-12">
|
|
Crypto
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-12">
|
|
Crypto
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../crypto/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../crypto/base64/" title="Base64" class="md-nav__link">
|
|
Base64
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../crypto/hash/" title="Hashes" class="md-nav__link">
|
|
Hashes
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../crypto/mac/" title="Message authentication" class="md-nav__link">
|
|
Message authentication
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../crypto/passwords/" title="Password hashing" class="md-nav__link">
|
|
Password hashing
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../crypto/random/" title="Random" class="md-nav__link">
|
|
Random
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-13" type="checkbox" id="nav-13">
|
|
|
|
<label class="md-nav__link" for="nav-13">
|
|
Testing
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-13">
|
|
Testing
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../testing/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-14" type="checkbox" id="nav-14">
|
|
|
|
<label class="md-nav__link" for="nav-14">
|
|
Deploy
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-14">
|
|
Deploy
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../deploy/getting-started/" title="Getting Started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-15" type="checkbox" id="nav-15">
|
|
|
|
<label class="md-nav__link" for="nav-15">
|
|
Version (3.0-rc)
|
|
</label>
|
|
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
|
<label class="md-nav__title" for="nav-15">
|
|
Version (3.0-rc)
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../version/1_5/" title="1.5" class="md-nav__link">
|
|
1.5
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../version/2_0/" title="2.0" class="md-nav__link">
|
|
2.0
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../version/3_0/" title="3.0-rc" class="md-nav__link">
|
|
3.0-rc
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../version/support/" title="Support" class="md-nav__link">
|
|
Support
|
|
</a>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
|
|
<nav class="md-nav md-nav--secondary">
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__title" for="toc">Table of contents</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#conformance" title="Conformance" class="md-nav__link">
|
|
Conformance
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#associated-types" title="Associated Types" class="md-nav__link">
|
|
Associated Types
|
|
</a>
|
|
|
|
<nav class="md-nav">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#database" title="Database" class="md-nav__link">
|
|
Database
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#id" title="ID" class="md-nav__link">
|
|
ID
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#properties" title="Properties" class="md-nav__link">
|
|
Properties
|
|
</a>
|
|
|
|
<nav class="md-nav">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#name" title="Name" class="md-nav__link">
|
|
Name
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#entity" title="Entity" class="md-nav__link">
|
|
Entity
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#id-key" title="ID Key" class="md-nav__link">
|
|
ID Key
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#lifecycle" title="Lifecycle" class="md-nav__link">
|
|
Lifecycle
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#crud" title="CRUD" class="md-nav__link">
|
|
CRUD
|
|
</a>
|
|
|
|
<nav class="md-nav">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#create" title="Create" class="md-nav__link">
|
|
Create
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#read" title="Read" class="md-nav__link">
|
|
Read
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#update" title="Update" class="md-nav__link">
|
|
Update
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#delete" title="Delete" class="md-nav__link">
|
|
Delete
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#methods" title="Methods" class="md-nav__link">
|
|
Methods
|
|
</a>
|
|
|
|
<nav class="md-nav">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#require-id" title="Require ID" class="md-nav__link">
|
|
Require ID
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="md-content">
|
|
<article class="md-content__inner md-typeset">
|
|
|
|
|
|
<a href="https://github.com/vapor/documentation/edit/master/3.0/docs/fluent/models.md" title="Edit this page" class="md-icon md-content__icon"></a>
|
|
|
|
|
|
<h1 id="fluent-models">Fluent Models<a class="headerlink" href="#fluent-models" title="Permanent link">¶</a></h1>
|
|
<p>Models are the heart of Fluent. Unlike ORMs in other languages, Fluent doesn't return untyped arrays or dictionaries for queries. Instead, you query the database using models. This allows the Swift compiler to catch many errors that have burdened ORM users for ages.</p>
|
|
<div class="admonition info">
|
|
<p class="admonition-title">Info</p>
|
|
<p>This guide provides an overview of the <code>Model</code> protocol and its associated methods and properties. If you are just getting started, check find the guide for your database at <a href="../getting-started/">Fluent → Getting Started</a>.</p>
|
|
</div>
|
|
<p><code>Model</code> is a protocol in the <code>Fluent</code> module. It extends the <code>AnyModel</code> protocol which can be used for type-erasure. </p>
|
|
<h2 id="conformance">Conformance<a class="headerlink" href="#conformance" title="Permanent link">¶</a></h2>
|
|
<p>Both <code>struct</code>s and <code>class</code>es can conform to <code>Model</code>, however you must pay special attention to Fluent's return types if you use a <code>struct</code>. Since Fluent works asynchronously, any mutations to a value-type (<code>struct</code>) model must return a new copy of the model as a future result.</p>
|
|
<p>Normally, you will conform your model to one of the convenience models available in your database-specific package (i.e., <code>PostgreSQLModel</code>). However, if you want to customize additional properties, such as the model's <code>idKey</code>, you will want to use the <code>Model</code> protocol itself.</p>
|
|
<p>Let's take a look at what a basic <code>Model</code> conformance looks like.</p>
|
|
<div class="codehilite"><pre><span></span><span class="c1">/// A simple user.</span>
|
|
<span class="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
|
|
<span class="c1">/// See `Model.Database`</span>
|
|
<span class="kd">typealias</span> <span class="n">Database</span> <span class="p">=</span> <span class="n">FooDatabase</span>
|
|
|
|
<span class="c1">/// See `Model.ID`</span>
|
|
<span class="kd">typealias</span> <span class="n">ID</span> <span class="p">=</span> <span class="nb">Int</span>
|
|
|
|
<span class="c1">/// See `Model.idKey`</span>
|
|
<span class="kd">static</span> <span class="kd">let</span> <span class="nv">idKey</span><span class="p">:</span> <span class="n">IDKey</span> <span class="p">=</span> <span class="err">\</span><span class="p">.</span><span class="n">id</span>
|
|
|
|
<span class="c1">/// The unique identifier for this user.</span>
|
|
<span class="kd">var</span> <span class="nv">id</span><span class="p">:</span> <span class="nb">Int</span><span class="p">?</span>
|
|
|
|
<span class="c1">/// The user's full name.</span>
|
|
<span class="kd">var</span> <span class="nv">name</span><span class="p">:</span> <span class="nb">String</span>
|
|
|
|
<span class="c1">/// The user's current age in years.</span>
|
|
<span class="kd">var</span> <span class="nv">age</span><span class="p">:</span> <span class="nb">Int</span>
|
|
|
|
<span class="c1">/// Creates a new user.</span>
|
|
<span class="kd">init</span><span class="p">(</span><span class="n">id</span><span class="p">:</span> <span class="nb">Int</span><span class="p">?</span> <span class="p">=</span> <span class="kc">nil</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span> <span class="n">age</span><span class="p">:</span> <span class="nb">Int</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kc">self</span><span class="p">.</span><span class="n">id</span> <span class="p">=</span> <span class="n">id</span>
|
|
<span class="kc">self</span><span class="p">.</span><span class="n">name</span> <span class="p">=</span> <span class="n">name</span>
|
|
<span class="kc">self</span><span class="p">.</span><span class="n">age</span> <span class="p">=</span> <span class="n">age</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<div class="admonition tip">
|
|
<p class="admonition-title">Tip</p>
|
|
<p>Using <code>final</code> prevents your class from being sub-classed. This makes your life easier.</p>
|
|
</div>
|
|
<h2 id="associated-types">Associated Types<a class="headerlink" href="#associated-types" title="Permanent link">¶</a></h2>
|
|
<p><code>Model</code> defines a few associated types that help Fluent create type-safe APIs for you to use. Take a look at <code>AnyModel</code> if you need a type-erased version with no associated types.</p>
|
|
<h3 id="database">Database<a class="headerlink" href="#database" title="Permanent link">¶</a></h3>
|
|
<p>This type indicates to Fluent which database you intend to use with this model. Using this information, Fluent can dynamically add appropriate methods and data types to any <code>QueryBuilder</code>s you create with this model.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
|
|
<span class="c1">/// See `Model.Database`</span>
|
|
<span class="kd">typealias</span> <span class="n">Database</span> <span class="p">=</span> <span class="n">FooDatabase</span>
|
|
<span class="c1">/// ...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>It is possible to make this associated type generic by adding a generic type to your class or struct (i.e, <code>User<T></code>). This is useful for cases where you are attempting to create generic extensions to Fluent, like perhaps an additive service provider.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p"><</span><span class="n">D</span><span class="p">>:</span> <span class="n">Model</span> <span class="k">where</span> <span class="n">D</span><span class="p">:</span> <span class="n">Database</span> <span class="p">{</span>
|
|
<span class="c1">/// See `Model.Database`</span>
|
|
<span class="kd">typealias</span> <span class="n">Database</span> <span class="p">=</span> <span class="n">D</span>
|
|
<span class="c1">/// ...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>You can add further conditions to <code>D</code>, such as <code>QuerySupporting</code> or <code>SchemaSupporting</code>. You can also dynamically extend and conform your generic model using <code>extension User where D: ... { }</code>.</p>
|
|
<p>That said, for most cases, you should stick to using a concrete type-alias wherever possible. Fluent 3 is designed to allow you to harness the power of your database by creating a strong connection between your models and the underlying driver. </p>
|
|
<h3 id="id">ID<a class="headerlink" href="#id" title="Permanent link">¶</a></h3>
|
|
<p>This property defines the type your model will use for its unique identifier.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
|
|
<span class="c1">/// See `Model.ID`</span>
|
|
<span class="kd">typealias</span> <span class="n">ID</span> <span class="p">=</span> <span class="n">UUID</span>
|
|
<span class="c1">/// ...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>This will usually be something like <code>Int</code>, <code>UUID</code>, or <code>String</code> although you can theoretically use any type you like.</p>
|
|
<h2 id="properties">Properties<a class="headerlink" href="#properties" title="Permanent link">¶</a></h2>
|
|
<p>There are several overridable properties on <code>Model</code> that you can use to customize how Fluent interacts with your database.</p>
|
|
<h3 id="name">Name<a class="headerlink" href="#name" title="Permanent link">¶</a></h3>
|
|
<p>This <code>String</code> will be used as a unique identifier for your model whenever Fluent needs one.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
|
|
<span class="c1">/// See `Model.name`</span>
|
|
<span class="kd">static</span> <span class="kd">let</span> <span class="nv">name</span> <span class="p">=</span> <span class="s">"user"</span>
|
|
<span class="c1">/// ...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>By default, this is the type name of your model lowercased.</p>
|
|
<h3 id="entity">Entity<a class="headerlink" href="#entity" title="Permanent link">¶</a></h3>
|
|
<p>Entity is a generic word used to mean either "table" or "collection", depending on which type of backend you are using for Fluent.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">Goose</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
|
|
<span class="c1">/// See `Model.entity`</span>
|
|
<span class="kd">static</span> <span class="kd">let</span> <span class="nv">entity</span> <span class="p">=</span> <span class="s">"geese"</span>
|
|
<span class="c1">/// ...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>By default, this property will be <a href="#name">name</a> pluralized. Overriding this property is useful in situations where language fails you and the plural form of a word is very irregular.</p>
|
|
<h3 id="id-key">ID Key<a class="headerlink" href="#id-key" title="Permanent link">¶</a></h3>
|
|
<p>The ID key is a writeable <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md">key path</a> that points to your model's unique identifier property.</p>
|
|
<p>Usually this will be a property named <code>id</code> (for some databases it is <code>_id</code>). However you can theoretically use any key you like.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
|
|
<span class="c1">/// See `Model.ID`</span>
|
|
<span class="kd">typealias</span> <span class="n">ID</span> <span class="p">=</span> <span class="nb">String</span>
|
|
|
|
<span class="c1">/// See `Model.entity`</span>
|
|
<span class="kd">static</span> <span class="kd">let</span> <span class="nv">idKey</span> <span class="p">=</span> <span class="err">\</span><span class="p">.</span><span class="n">username</span>
|
|
|
|
<span class="c1">/// The user's unique username</span>
|
|
<span class="kd">var</span> <span class="nv">username</span><span class="p">:</span> <span class="nb">String</span><span class="p">?</span>
|
|
|
|
<span class="c1">/// ...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>The <code>idKey</code> property must point to an optional, writeable (<code>var</code>) property with type matching <a href="#id">ID</a>.</p>
|
|
<h2 id="lifecycle">Lifecycle<a class="headerlink" href="#lifecycle" title="Permanent link">¶</a></h2>
|
|
<p>There are several lifecycle methods on <code>Model</code> that you can override to hook into Fluent events.</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>method</th>
|
|
<th>description</th>
|
|
<th>throwing</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>willCreate</code></td>
|
|
<td>Called before Fluent saves your model (for the first time)</td>
|
|
<td>Cancels the save.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>didCreate</code></td>
|
|
<td>Called after Fluent saves your model (for the first time)</td>
|
|
<td>Save completes. Query fails.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>willUpdate</code></td>
|
|
<td>Called before Fluent saves your model (subsequent saves)</td>
|
|
<td>Cancels the save.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>didUpdate</code></td>
|
|
<td>Called after Fluent saves your model (subsequent saves)</td>
|
|
<td>Save completes. Query fails.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>willRead</code></td>
|
|
<td>Called before Fluent returns your model from a fetch query.</td>
|
|
<td>Cancels the fetch.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>willDelete</code></td>
|
|
<td>Called before Fluent deletes your model.</td>
|
|
<td>Cancels the delete.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p>Here's an example of overriding the <code>willUpdate(on:)</code> method.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
|
|
<span class="c1">/// ...</span>
|
|
|
|
<span class="c1">/// See `Model.willUpdate(on:)`</span>
|
|
<span class="kd">func</span> <span class="nf">willUpdate</span><span class="p">(</span><span class="n">on</span> <span class="n">connection</span><span class="p">:</span> <span class="n">Database</span><span class="p">.</span><span class="n">Connection</span><span class="p">)</span> <span class="kr">throws</span> <span class="p">-></span> <span class="n">Future</span><span class="p"><</span><span class="kc">Self</span><span class="p">></span> <span class="p">{</span>
|
|
<span class="c1">/// Throws an error if the username is invalid</span>
|
|
<span class="k">try</span> <span class="n">validateUsername</span><span class="p">()</span>
|
|
|
|
<span class="c1">/// Return the user. No async work is being done, so we must create a future manually.</span>
|
|
<span class="k">return</span> <span class="n">Future</span><span class="p">.</span><span class="bp">map</span><span class="p">(</span><span class="n">on</span><span class="p">:</span> <span class="n">connection</span><span class="p">)</span> <span class="p">{</span> <span class="kc">self</span> <span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<h2 id="crud">CRUD<a class="headerlink" href="#crud" title="Permanent link">¶</a></h2>
|
|
<p>The model offers basic CRUD method (create, read, update, delete).</p>
|
|
<h3 id="create">Create<a class="headerlink" href="#create" title="Permanent link">¶</a></h3>
|
|
<p>This method creates a new row / item for an instance of your model in the database.</p>
|
|
<p>If your model does not have an ID, calls to <code>.save(on:)</code> will redirect to this method.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kd">let</span> <span class="nv">didCreate</span> <span class="p">=</span> <span class="n">user</span><span class="p">.</span><span class="n">create</span><span class="p">(</span><span class="n">on</span><span class="p">:</span> <span class="n">req</span><span class="p">)</span>
|
|
<span class="bp">print</span><span class="p">(</span><span class="n">didCreate</span><span class="p">)</span> <span class="c1">/// Future<User></span>
|
|
</pre></div>
|
|
|
|
|
|
<div class="admonition info">
|
|
<p class="admonition-title">Info</p>
|
|
<p>If you are using a value-type (<code>struct</code>), the instance of your model returned by <code>.create(on:)</code> will contain the model's new ID.</p>
|
|
</div>
|
|
<h3 id="read">Read<a class="headerlink" href="#read" title="Permanent link">¶</a></h3>
|
|
<p>Two methods are important for reading your model from the database, <code>find(_:on:)</code> and <code>query(on:)</code>.</p>
|
|
<div class="codehilite"><pre><span></span><span class="c1">/// Finds a user with ID == 1</span>
|
|
<span class="kd">let</span> <span class="nv">user</span> <span class="p">=</span> <span class="n">User</span><span class="p">.</span><span class="bp">find</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">on</span><span class="p">:</span> <span class="n">req</span><span class="p">)</span>
|
|
<span class="bp">print</span><span class="p">(</span><span class="n">user</span><span class="p">)</span> <span class="c1">/// Future<User?></span>
|
|
</pre></div>
|
|
|
|
|
|
<div class="codehilite"><pre><span></span><span class="c1">/// Finds all users with name == "Vapor"</span>
|
|
<span class="kd">let</span> <span class="nv">users</span> <span class="p">=</span> <span class="n">User</span><span class="p">.</span><span class="n">query</span><span class="p">(</span><span class="n">on</span><span class="p">:</span> <span class="n">req</span><span class="p">).</span><span class="bp">filter</span><span class="p">(</span><span class="err">\</span><span class="p">.</span><span class="n">name</span> <span class="p">==</span> <span class="s">"Vapor"</span><span class="p">).</span><span class="n">all</span><span class="p">()</span>
|
|
<span class="bp">print</span><span class="p">(</span><span class="n">users</span><span class="p">)</span> <span class="c1">/// Future<[User]></span>
|
|
</pre></div>
|
|
|
|
|
|
<h3 id="update">Update<a class="headerlink" href="#update" title="Permanent link">¶</a></h3>
|
|
<p>This method updates the existing row / item associated with an instance of your model in the database.</p>
|
|
<p>If your model already has an ID, calls to <code>.save(on:)</code> will redirect to this method.</p>
|
|
<div class="codehilite"><pre><span></span><span class="c1">/// Updates the user</span>
|
|
<span class="kd">let</span> <span class="nv">didUpdate</span> <span class="p">=</span> <span class="n">user</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="n">on</span><span class="p">:</span> <span class="n">req</span><span class="p">)</span>
|
|
<span class="bp">print</span><span class="p">(</span><span class="n">didUpdate</span><span class="p">)</span> <span class="c1">/// Future<User></span>
|
|
</pre></div>
|
|
|
|
|
|
<h3 id="delete">Delete<a class="headerlink" href="#delete" title="Permanent link">¶</a></h3>
|
|
<p>This method deletes the existing row / item associated with an instance of your model from the database.</p>
|
|
<div class="codehilite"><pre><span></span><span class="c1">/// Deletes the user</span>
|
|
<span class="kd">let</span> <span class="nv">didDelete</span> <span class="p">=</span> <span class="n">user</span><span class="p">.</span><span class="n">delete</span><span class="p">(</span><span class="n">on</span><span class="p">:</span> <span class="n">req</span><span class="p">)</span>
|
|
<span class="bp">print</span><span class="p">(</span><span class="n">didDelete</span><span class="p">)</span> <span class="c1">/// Future<Void></span>
|
|
</pre></div>
|
|
|
|
|
|
<h2 id="methods">Methods<a class="headerlink" href="#methods" title="Permanent link">¶</a></h2>
|
|
<p><code>Model</code> offers some convenience methods to make working with it easier.</p>
|
|
<h3 id="require-id">Require ID<a class="headerlink" href="#require-id" title="Permanent link">¶</a></h3>
|
|
<p>This method return's the models ID or throws an error.</p>
|
|
<div class="codehilite"><pre><span></span><span class="kd">let</span> <span class="nv">id</span> <span class="p">=</span> <span class="k">try</span> <span class="n">user</span><span class="p">.</span><span class="n">requireID</span><span class="p">()</span>
|
|
</pre></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</article>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
|
|
<footer class="md-footer">
|
|
|
|
<div class="md-footer-nav">
|
|
<nav class="md-footer-nav__inner md-grid">
|
|
|
|
<a href="../getting-started/" title="Getting Started" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
|
|
<div class="md-flex__cell md-flex__cell--shrink">
|
|
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
|
|
</div>
|
|
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
|
|
<span class="md-flex__ellipsis">
|
|
<span class="md-footer-nav__direction">
|
|
Previous
|
|
</span>
|
|
Getting Started
|
|
</span>
|
|
</div>
|
|
</a>
|
|
|
|
|
|
<a href="../migrations/" title="Migrations" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
|
|
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
|
|
<span class="md-flex__ellipsis">
|
|
<span class="md-footer-nav__direction">
|
|
Next
|
|
</span>
|
|
Migrations
|
|
</span>
|
|
</div>
|
|
<div class="md-flex__cell md-flex__cell--shrink">
|
|
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
|
|
</div>
|
|
</a>
|
|
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="md-footer-meta md-typeset">
|
|
<div class="md-footer-meta__inner md-grid">
|
|
<div class="md-footer-copyright">
|
|
|
|
<div class="md-footer-copyright__highlight">
|
|
Copyright © 2018 Qutheory, LLC
|
|
</div>
|
|
|
|
powered by
|
|
<a href="http://www.mkdocs.org">MkDocs</a>
|
|
and
|
|
<a href="https://squidfunk.github.io/mkdocs-material/">
|
|
Material for MkDocs</a>
|
|
</div>
|
|
|
|
|
|
<div class="md-footer-social">
|
|
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
|
|
|
<a href="https://twitter.com/@codevapor" class="md-footer-social__link fa fa-twitter"></a>
|
|
|
|
<a href="http://vapor.team/" class="md-footer-social__link fa fa-slack"></a>
|
|
|
|
<a href="https://github.com/vapor" class="md-footer-social__link fa fa-github"></a>
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
</div>
|
|
|
|
<script src="../../assets/javascripts/application.8eb9be28.js"></script>
|
|
|
|
<script>app.initialize({version:"0.17.3",url:{base:"../.."}})</script>
|
|
|
|
|
|
|
|
|
|
<script>!function(e,a,t,n,o,c,i){e.GoogleAnalyticsObject=o,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(t),i=a.getElementsByTagName(t)[0],c.async=1,c.src="https://www.google-analytics.com/analytics.js",i.parentNode.insertBefore(c,i)}(window,document,"script",0,"ga"),ga("create","UA-76177358-4","auto"),ga("set","anonymizeIp",!0),ga("send","pageview");var links=document.getElementsByTagName("a");if(Array.prototype.map.call(links,function(e){e.host!=document.location.host&&e.addEventListener("click",function(){var a=e.getAttribute("data-md-action")||"follow";ga("send","event","outbound",a,e.href)})}),document.forms.search){var query=document.forms.search.query;query.addEventListener("blur",function(){if(this.value){var e=document.location.pathname;ga("send","pageview",e+"?q="+this.value)}})}</script>
|
|
|
|
|
|
</body>
|
|
</html> |