This commit is contained in:
tanner0101 2018-03-13 20:32:20 -04:00
parent 5b3eee9cd3
commit af829dbe07
3 changed files with 473 additions and 122 deletions

View File

@ -93,7 +93,7 @@
<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="#getting-started-with-models" tabindex="1" class="md-skip">
<a href="#fluent-models" tabindex="1" class="md-skip">
Skip to content
</a>
@ -596,15 +596,15 @@
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#class" title="Class" class="md-nav__link">
Class
<a href="#conformance" title="Conformance" class="md-nav__link">
Conformance
</a>
</li>
<li class="md-nav__item">
<a href="#conforming-to-model" title="Conforming to Model" class="md-nav__link">
Conforming to Model
<a href="#associated-types" title="Associated Types" class="md-nav__link">
Associated Types
</a>
<nav class="md-nav">
@ -630,17 +630,105 @@
</li>
<li class="md-nav__item">
<a href="#example" title="Example" class="md-nav__link">
Example
<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="#done" title="Done" class="md-nav__link">
Done
<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>
@ -1376,15 +1464,15 @@
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#class" title="Class" class="md-nav__link">
Class
<a href="#conformance" title="Conformance" class="md-nav__link">
Conformance
</a>
</li>
<li class="md-nav__item">
<a href="#conforming-to-model" title="Conforming to Model" class="md-nav__link">
Conforming to Model
<a href="#associated-types" title="Associated Types" class="md-nav__link">
Associated Types
</a>
<nav class="md-nav">
@ -1410,17 +1498,105 @@
</li>
<li class="md-nav__item">
<a href="#example" title="Example" class="md-nav__link">
Example
<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="#done" title="Done" class="md-nav__link">
Done
<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>
@ -1442,113 +1618,238 @@
<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">&#xE3C9;</a>
<h1 id="getting-started-with-models">Getting Started with Models<a class="headerlink" href="#getting-started-with-models" title="Permanent link">&para;</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>
<p>In this guide, we will cover the creation of a basic <code>User</code> model.</p>
<h2 id="class">Class<a class="headerlink" href="#class" title="Permanent link">&para;</a></h2>
<p>Every Fluent model starts with a <code>Codable</code> class. You can make any <code>Codable</code> class a Fluent model,
even ones that come from a different module. All you have to do is conform to <code>Model</code>.</p>
<div class="codehilite"><pre><span></span><span class="kd">import</span> <span class="nc">Foundation</span>
<span class="kd">import</span> <span class="nc">Vapor</span>
<h1 id="fluent-models">Fluent Models<a class="headerlink" href="#fluent-models" title="Permanent link">&para;</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 &rarr; 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">&para;</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="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Content</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nv">id</span><span class="p">:</span> <span class="n">UUID</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">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&#39;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&#39;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>
<p>Although it's not necessary, adding <code>final</code> to your Swift classes can make them more performant
and also make adding <code>init</code> methods in extensions easier.</p>
<h2 id="conforming-to-model">Conforming to Model<a class="headerlink" href="#conforming-to-model" title="Permanent link">&para;</a></h2>
<p>Now that we have our <code>User</code> class, let's conform it to <code>Model</code>.</p>
<div class="codehilite"><pre><span></span><span class="kd">import</span> <span class="nc">FluentMySQL</span>
<span class="kd">extension</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
<span class="p">}</span>
</pre></div>
<p>Once you add this conformance requirement, Swift will tell you that it does not yet conform.
Let's add the necessary items to make <code>User</code> conform to model.</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>We recommend adding <code>Model</code> conformance in an extension to help keep your code clean.</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">&para;</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">&para;</a></h3>
<p>The first step to conforming to <code>Model</code> is to let Fluent know which type of database you plan
on using this model with. This allows Fluent to enable database-specific features wherever you
use this model.</p>
<div class="codehilite"><pre><span></span><span class="kd">import</span> <span class="nc">FluentMySQL</span>
<span class="kd">extension</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</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">MySQLDatabase</span>
<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&lt;T&gt;</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">&lt;</span><span class="n">D</span><span class="p">&gt;:</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">&para;</a></h3>
<p>Now we can tell Fluent what type of ID this model uses. In this example, our <code>User</code> model
has an ID property of type <code>UUID</code> named <code>id</code>.</p>
<div class="codehilite"><pre><span></span><span class="kd">import</span> <span class="nc">FluentMySQL</span>
<span class="kd">import</span> <span class="nc">Foundation</span>
<span class="kd">extension</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Model</span> <span class="p">{</span>
<span class="p">...</span>
<span class="c1">/// See Model.ID</span>
<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>
<span class="c1">/// See Model.idKey</span>
<span class="kd">static</span> <span class="kd">var</span> <span class="nv">idKey</span><span class="p">:</span> <span class="n">IDKey</span> <span class="p">{</span>
<span class="k">return</span> <span class="err">\</span><span class="p">.</span><span class="n">id</span>
<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">&para;</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">&para;</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">&quot;user&quot;</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">&para;</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">&quot;geese&quot;</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">&para;</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&#39;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">&para;</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">-&gt;</span> <span class="n">Future</span><span class="p">&lt;</span><span class="kc">Self</span><span class="p">&gt;</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>
<p>You can use any type that conforms to <code>IDType</code> as a Fluent ID. You can also use any property name you'd like for the id.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Some databases require certain ID keys. For example, MongoDB requires <code>_id</code>.</p>
<h2 id="crud">CRUD<a class="headerlink" href="#crud" title="Permanent link">&para;</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">&para;</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&lt;User&gt;</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>
<h2 id="example">Example<a class="headerlink" href="#example" title="Permanent link">&para;</a></h2>
<p>We now have a fully-conformed Fluent model!</p>
<div class="codehilite"><pre><span></span><span class="kd">import</span> <span class="nc">FluentMySQL</span>
<span class="kd">import</span> <span class="nc">Foundation</span>
<span class="kd">import</span> <span class="nc">Vapor</span>
<span class="kr">final</span> <span class="kd">class</span> <span class="nc">User</span><span class="p">:</span> <span class="n">Codable</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nv">id</span><span class="p">:</span> <span class="n">UUID</span><span class="p">?</span>
<span class="kd">var</span> <span class="nv">name</span><span class="p">:</span> <span class="nb">String</span>
<span class="kd">var</span> <span class="nv">age</span><span class="p">:</span> <span class="nb">Int</span>
<span class="p">}</span>
<span class="kd">extension</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">MySQLDatabase</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">/// See Model.idKey</span>
<span class="kd">static</span> <span class="kd">var</span> <span class="nv">idKey</span><span class="p">:</span> <span class="n">IDKey</span> <span class="p">{</span>
<span class="k">return</span> <span class="err">\</span><span class="p">.</span><span class="n">id</span>
<span class="p">}</span>
<span class="p">}</span>
<h3 id="read">Read<a class="headerlink" href="#read" title="Permanent link">&para;</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&lt;User?&gt;</span>
</pre></div>
<h2 id="done">Done<a class="headerlink" href="#done" title="Permanent link">&para;</a></h2>
<p>Now that you have a working Fluent model, you can move onto <a href="../querying/">querying</a> your model.
However, if your database uses schemas, you may need to create a <a href="../migrations/">migration</a> for your model first.</p>
<div class="codehilite"><pre><span></span><span class="c1">/// Finds all users with name == &quot;Vapor&quot;</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">&quot;Vapor&quot;</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&lt;[User]&gt;</span>
</pre></div>
<h3 id="update">Update<a class="headerlink" href="#update" title="Permanent link">&para;</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&lt;User&gt;</span>
</pre></div>
<h3 id="delete">Delete<a class="headerlink" href="#delete" title="Permanent link">&para;</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&lt;Void&gt;</span>
</pre></div>
<h2 id="methods">Methods<a class="headerlink" href="#methods" title="Permanent link">&para;</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">&para;</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>

View File

@ -1650,7 +1650,7 @@
</tr>
</tbody>
</table>
<p>If you look at the method signatures for <code>map</code> and <code>flatMap</code> on <code>Optional&lt;T&gt;</code> and <code>Array&lt;T&gt;</code>, you will see the are very similar to the methods available on <code>Future&lt;T&gt;</code>.</p>
<p>If you look at the method signatures for <code>map</code> and <code>flatMap</code> on <code>Optional&lt;T&gt;</code> and <code>Array&lt;T&gt;</code>, you will see that they are very similar to the methods available on <code>Future&lt;T&gt;</code>.</p>
<h3 id="map">Map<a class="headerlink" href="#map" title="Permanent link">&para;</a></h3>
<p>The <code>.map(to:_:)</code> method allows you to transform the future's value to another value. Because the future's value may not be available yet (it may be the result of an asynchronous task) we must provide a closure to accept the value.</p>
<div class="codehilite"><pre><span></span><span class="c1">/// Assume we get a future string back from some API</span>
@ -1668,7 +1668,7 @@
<h3 id="flat-map">Flat Map<a class="headerlink" href="#flat-map" title="Permanent link">&para;</a></h3>
<p>The <code>.flatMap(to:_:)</code> method allows you to transform the future's value to another future value. It gets the name "flat" map because it is what allows you to avoid creating nested futures (i.e., <code>Future&lt;Future&lt;T&gt;&gt;</code>). In other words, it helps you keep your generic futures flat.</p>
<p>The <code>.flatMap(to:_:)</code> method allows you to transform the future's value to another future value. It gets the name "flat" map because it is what allows you to avoid creating nested futures (e.g., <code>Future&lt;Future&lt;T&gt;&gt;</code>). In other words, it helps you keep your generic futures flat.</p>
<div class="codehilite"><pre><span></span><span class="c1">/// Assume we get a future string back from some API</span>
<span class="kd">let</span> <span class="nv">futureString</span><span class="p">:</span> <span class="n">Future</span><span class="p">&lt;</span><span class="nb">String</span><span class="p">&gt;</span> <span class="p">=</span> <span class="p">...</span>
@ -1805,7 +1805,7 @@
<h3 id="thread-safety">Thread Safety<a class="headerlink" href="#thread-safety" title="Permanent link">&para;</a></h3>
<p>Promises can be completed (<code>succeed(result:)</code> / <code>fail(error:)</code>) from any thread. This is why promises require an event-loop to be initialized. Promises ensure that the completion action gets returned to its event-loop for execution.</p>
<h2 id="event-loop">Event Loop<a class="headerlink" href="#event-loop" title="Permanent link">&para;</a></h2>
<p>When your application boots, it will usually create one event loop for each core in the CPU it is running on. Each event loop has exactly one thread. If you are familiar with event loops from Node.js, the one's in Vapor are very similar. The only difference is that Vapor can run multiple event loops in one process since Swift supports multi-threading.</p>
<p>When your application boots, it will usually create one event loop for each core in the CPU it is running on. Each event loop has exactly one thread. If you are familiar with event loops from Node.js, the ones in Vapor are very similar. The only difference is that Vapor can run multiple event loops in one process since Swift supports multi-threading.</p>
<p>Each time a client connects to your server, it will be assigned to one of the event loops. From that point on, all communication between the server and that client will happen on that same event loop (and by association, that event loop's thread). </p>
<p>The event loop is responsible for keeping track of each connected client's state. If there is a request from the client waiting to be read, the event loop trigger a read notification, causing the data to be read. Once the entire request is read, any futures waiting for that request's data will be completed. </p>
<h3 id="worker">Worker<a class="headerlink" href="#worker" title="Permanent link">&para;</a></h3>

File diff suppressed because one or more lines are too long