チュートリアル:Fluentを使用してモデルを作成する方法

このチュートリアルでは、単純なユーザーモデルを実装し、データベースに格納し、データベースから戻して、ビューに渡す方法を示します。

このチュートリアルの結果は、githubでここにあります

このチュートリアルは、リーフの使用方法の自然なフォローアップです。最初にそのチュートリアルに進んで後で戻ってくるか、反逆者になってスキップしてonを読むことができます

索引

1.新しいプロジェクトを作成する
2. Xcodeプロジェクトを生成する
3. SQLiteデータベースを使用するようにプロジェクトを構成します
4.最初のモデルを作成する
5. GETルートを実装して、すべてのユーザーをリストします
6.非同期の説明
7. F ..の将来
8.ビューを作成する
9. POSTルートを実装してユーザーを保存する
10.ここからどこへ行くか

1.新しいプロジェクトを作成する

前述のチュートリアルの結果をテンプレートとして使用して、新しいプロジェクトを作成します。

vapor new projectName --template = vaporberlin / my-first-leaf-template

2. Xcodeプロジェクトを生成する

Xcodeプロジェクトを生成する前に、データベースプロバイダーを追加する必要があります。すべてのデータベースにそれぞれあります。しかし、ORM Fluentで暖かくするために、メモリ内データベースを使用します。そのため、Fluent-SQLiteをPackage.swift内の依存関係として追加します。

// swift-tools-version:4.0
PackageDescriptionのインポート
let package = Package(
  name: "projectName"、//変更
  依存関係:[
    .package(url: "https://github.com/vapor/vapor.git"、from: "3.0.0")、
    .package(url: "https://github.com/vapor/leaf.git"、from: "3.0.0-rc")、
   .package(url: "https://github.com/vapor/fluent-sqlite.git"、from: "3.0.0-rc")//追加
  ]、
  ターゲット:[
    .target(name: "App"、依存関係:["Vapor"、 "Leaf"、 "FluentSQLite"])、//追加
    .target(name: "Run"、依存関係:["App"])、
    .testTarget(name: "AppTests"、依存関係:["App"])、
  ]
)

次に、ターミナルでルートディレクトリprojectName /を実行します。

蒸気更新-y

依存関係を取得し、Xcodeプロジェクトを生成してそれを開くのに少し時間がかかる場合があります。完了したら、次のようなプロジェクト構造が必要です。

projectName /
├──Package.swift
├──ソース/
│├──アプリ/
││├──app.swift
││├──boot.swift
││├──configure.swift
││└──routes.swift
│└──実行/
│└──main.swift
├──テスト/
├──リソース/
├──公開/
├──依存関係/
└──製品/
cmd + rで「CNIOOpenSSL」を含むエラーが表示された場合、依存関係が欠落しています。 brew upgrade vaporを実行してプロジェクトを再生成するだけです

3. SQLiteデータベースを使用するようにプロジェクトを構成します

最初のステップは、configure.swift内にFluentSQLiteProviderを追加することです。

輸入蒸気
インポートリーフ
FluentSQLiteのインポート//追加
public func configure(
  _ config:inout Config、
  _ env:inout環境、
  _サービス:inoutサービス
)throws {
  //ルーターにルートを登録します
  let router = EngineRouter.default()
  ルートを試す(ルーター)
  services.register(router、as:Router.self)
  let leafProvider = LeafProvider()
  services.register(leafProvider)を試してください
  try services.register(FluentSQLiteProvider())//追加
  config.prefer(LeafRenderer.self、for:ViewRenderer.self)
}

次に、データベースサービスを開始し、それにSQLiteDatabaseを追加して、そのデータベースサービスを登録します。

輸入蒸気
インポートリーフ
FluentSQLiteをインポートする
public func configure(
  _ config:inout Config、
  _ env:inout環境、
  _サービス:inoutサービス
)throws {
  //ルーターにルートを登録します
  let router = EngineRouter.default()
  ルートを試す(ルーター)
  services.register(router、as:Router.self)
  let leafProvider = LeafProvider()
  services.register(leafProvider)を試してください
  services.register(FluentSQLiteProvider())を試してください
  config.prefer(LeafRenderer.self、for:ViewRenderer.self)
  var databases = DatabasesConfig()
  databases.add(database:SQLiteDatabase(storage:.memory)、as:.sqlite)を試してください
  services.register(データベース)
}

最後に、モデルをデータベースに導入するために後で使用する移行サービスを開始して登録します。今のところ、以下を追加します。

輸入蒸気
インポートリーフ
FluentSQLiteをインポートする
public func configure(
  _ config:inout Config、
  _ env:inout環境、
  _サービス:inoutサービス
)throws {
  //ルーターにルートを登録します
  let router = EngineRouter.default()
  ルートを試す(ルーター)
  services.register(router、as:Router.self)
  let leafProvider = LeafProvider()
  services.register(leafProvider)を試してください
  services.register(FluentSQLiteProvider())を試してください
  config.prefer(LeafRenderer.self、for:ViewRenderer.self)
  var databases = DatabaseConfig()
  databases.add(database:SQLiteDatabase(storage:.memory)、as:.sqlite)を試してください
  services.register(データベース)
  var migrations = MigrationConfig()
  services.register(migrations)
}

4.最初のモデルを作成する

Sources / App /内にディレクトリを作成し、Models /という名前を付け、その新しいディレクトリ内にUser.swiftという名前の新しいswiftファイルを作成します

注:mkdir Sources / App / Models /を実行するターミナルを使用し、Sources / App / Models / User.swiftをタッチします

Xcodeに新しいディレクトリを表示させるには、vapor xcode -yを使用してXcodeプロジェクトを再生成する必要があります。

Models / User.swiftに次のコードを含めます。

FluentSQLiteをインポートする
輸入蒸気
最終クラスユーザー:SQLiteModel {
  var id:Int?
  var username:文字列
  init(id:Int?= nil、username:String){
    self.id = id
    self.username =ユーザー名
  }
}
拡張ユーザー:コンテンツ{}
拡張ユーザー:移行{}

ここで何が起こっているかを理解できるように、非常にシンプルに保ちました。 SQLiteModelに準拠するには、int型のidというオプションの変数を定義する必要があります。データベースに保存するために新しいユーザーを開始する場合、その時点で彼にIDを与えるのは私たち次第ではないからです。彼は彼をデータベースに保存した後にIDを割り当てられます。

Contentに準拠しているため、ルートで返される場合、ユーザーはCodableを使用して、たとえばJSONに変換できます。または、彼はリーフビュー内で使用されるTemplateDataに変換できます。 Codableにより、自動的に行われます。 FluentはCodableを使用して最適なデータベーステーブルスキーマを作成し、configure.swiftで移行サービスに追加できるように、移行に準拠する必要があります。

輸入蒸気
インポートリーフ
FluentSQLiteをインポートする
public func configure(
  _ config:inout Config、
  _ env:inout環境、
  _サービス:inoutサービス
)throws {
  //ルーターにルートを登録します
  let router = EngineRouter.default()
  ルートを試す(ルーター)
  services.register(router、as:Router.self)
  let leafProvider = LeafProvider()
  services.register(leafProvider)を試してください
  services.register(FluentSQLiteProvider())を試してください
  config.prefer(LeafRenderer.self、for:ViewRenderer.self)
  var databases = DatabaseConfig()
  databases.add(database:SQLiteDatabase(storage:.memory)、as:.sqlite)を試してください
  services.register(データベース)
  var migrations = MigrationConfig()
  migrations.add(モデル:User.self、データベース:.sqlite)
  services.register(migrations)
}

cmd + rを実行するか、すべてを実行すると、すべてがうまくいくはずです。

注:アプリを実行する前に、ボタンの横にあるスキームとして実行を選択してください

5. GETルートを実装して、すべてのユーザーをリストします

データベースにはまだユーザーはいませんが、独自のフォームを使用してユーザーを作成して保存します。したがって、今のところroutes.swiftに行き、そのファイルのすべてを削除して、最終的には次のようになります:

輸入蒸気
インポートリーフ
public func routes(_ router:Router)throws {
  //ここには何もない
}

データベースからすべてのユーザーをフェッチするURLユーザーでgetルートを定義し、それらをビューに渡します。

輸入蒸気
インポートリーフ
public func routes(_ router:Router)throws {
  
  router.get( "users"){req-> Future  in
    return User.query(on:req).all()。flatMap {users in
      let data = ["userlist":users]
      return req.view()。render( "userview"、data)
    }
  }
}

ワオ。ここでは多くのことが行われています。しかし、心配する必要はありません。見た目よりもはるかに簡単です。このブラックマジックをさらに読み、理解すれば素晴らしい気分になります

VAPOR 3は先物に関するものです。そして、それは現在その性質が非同期であることに由来しています。

6.非同期の説明

人生の例を見てみましょう。蒸気2で、男の子がガールフレンドからソフトアイスとドーナツを買うように言われた場合。彼はアイスワゴンに行き、アイスを注文し、準備ができるまで待ちます。それから彼は続けてドーナツショップに行き、1つを買って、両方で彼のガールフレンドに戻ります。

Vapor 3では、少年はアイスワゴンに行き、氷を注文し、氷が作られたら、ドーナツショップに行き、ドーナツを買います。彼は氷の準備ができたときにアイスワゴンに戻り、それを取得し、両方で彼のガールフレンドに戻ります。

蒸気2:少年は、進むことができるまで、氷の注文によってブロックされて終了しました。
蒸気3:少年はノンブロッキングで仕事をし、他のタスクに彼の待ち時間を使います。

7. F ..の将来

何が起こっているのか、そしてその理由を理解しましょう。 Userクラスを使用してデータベースを照会しています。そして、リクエストの裏でそのクエリを実行するように読むことができます。リクエストは男の子だと考えてください。私たちのために仕事をする人。労働者。

わかりましたので、ユーザーの配列はありませんが、ユーザーの配列の未来:Future <[Users]>。そして正直に。それでおしまい。それが私が意味するのは、特別なものや特別なものは何もないということです。それだけです。未来に「包まれる」だけです。私たちが気にしている唯一のことは、私たちが慣れ親しんでいる方法で作業したい場合、母親の名前でどのようにデータを未来から取り出すかです

そこで、mapまたはflatMapが役立ちます。

呼び出しの本文が将来の値を返さない場合、マップを選択します。

someFuture.map {データ入力
  戻り値
}

そして、本文が将来の値を返す場合、flatMapを呼び出します。

someFuture.flatMap {データ入力
  Future を返します
}

この単純なルールのみがあります。各マップ関数で何かを返す必要があるため、flatMapを使用するのかマップを使用するのかが、その何かがわかるからです。ルールは次のとおりです。その何かがFutureである場合はflatMapを使用し、それが「通常の」データである場合はマップを使用します。

したがって、このルートでは、ビューに渡すためにユーザーの配列にアクセスします。したがって、両方のマップ関数のいずれかが必要です。そして、render()関数が返すものは何でも返すので。それをcmd +クリックすると、Future であることがわかります。Futureを返す場合はflatMapを使用します。

そして、ここでそれがすべてです。奇妙で新しいと感じ、それほど直感的ではない場合は心配ありません。そして、何をどのように使用するかをあなたが知っているような気がしません。それが私がここにいることです(願わくば)。チュートリアルに従って、私またはDiscordのコミュニティにあらゆる種類の質問をして、クリックしてくれると信じてください!正直に言うと、それがクリックされるまでクリックするかどうかはわかりませんでした。時間を与えてください!

8.ビューを作成する

Resources / Views /内で、そこにあるすべてのファイル(welcome.leafとwhoami.leaf)を削除し、userview.leafという名前の新しいファイルを作成して追加します。

<!DOCTYPE html>

  
    モデル</ title>
    <link href = "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel = "stylesheet">
  </ head>
  <body class = "container">
    <h1 class = "mt-3">ユーザーリスト</ h1></pre><pre>    <form method = "POST" action = "/ users">
      <div class = "input-group">
        <input type = "text" name = "username" class = "form-control">
          <div class = "input-group-append">
            <button class = "btn btn-outline-secondary" type = "submit">
              作成する
            </ button>
          </ div>
      </ div>
    </ form></pre><pre>    #for(userlistのユーザー){
      <p class = "mb-0">
        #(user.username)
      </ p>
    }
  </ body>
</ html></pre><p>ここで興味深いことをマークしました。 <link>タグを使用して、CSSフレームワークであるブートストラップを追加するだけで、ビューが少し見やすくなります。</p><p><form>タグを使用して、フォームを送信したときに何が起こるかを定義します。これは、メソッドpostを使用して/ usersで実行されます。その投稿ルートをすぐに実装します。</p><p><input type =” text” name =” username”>は、新しいユーザー名を書き込むための入力フィールドです。ここでは、name =” username”はテキストが接続されるキーであるため、非常に重要です。投稿ルートを作成するときに私が意味することを理解するでしょう。</p><p>#for()ループはリーフ固有のタグで、以前にビューに["userlist":…]として渡したユーザーリストを反復処理し、#(user.username)を使用すると、swiftのようにオブジェクトにアクセスできます。</p><p>プロジェクトをcmd + rまたは実行して/ usersでサイトを起動すると、ヘッダー、入力フィールド、およびボタンが表示されます。そしてそれはまったく問題ありません。ユーザーのリストは、作成するとすぐに表示されます。やってみましょう!</p><img alt="" src="https://imgstore.nyc3.cdn.digitaloceanspaces.com/ceadesc/1568900870836.png" /><h4>9. POSTルートを実装してユーザーを保存する</h4><p>routes.swiftに次のコードを追加します。</p><pre>輸入蒸気
インポートリーフ</pre><pre>public func routes(_ router:Router)throws {</pre><pre>  router.get( "users"){req-> Future <View> in
    ...
  }</pre><pre>  router.post( "users"){req-> Future <Response> in
    return req.content.decode(User.self).flatMap {user in
      return user.save(on:req).map {_ in
        return req.redirect(to: "users")
      }
    }
  }
}</pre><p>送信ボタンを押してビューでフォームを送信すると、入力フィールドデータform-url-encodedが/ usersルートに次のような投稿として送信されます。</p><pre>username = MartinLasek</pre><p>ユーザーモデルは1つのプロパティユーザー名のみで構成され、プロトコルContentに準拠しているため、フォームからユーザーのインスタンスに送信されるコンテンツをデコードできます。 Int型の年齢のような別のプロパティをUserクラスに追加し、プロジェクトを再実行して、フォームを再度送信してみてください。パスの年齢でIntが見つからなかったことがわかります。フォームはユーザー名とともにage = 23を送信しないためです。</p><p>ただし、decodeはユーザーインスタンスのFutureを返すため、それにアクセスするにはmap / flatMap関数のいずれかを使用する必要があります。さて、小さなサイドノート。両方の機能は全体としてFutureになります。これらの機能の本体については話していない。私は全体の呼び出しについて話している。デコード時にflatMapを呼び出す理由を説明しているため、重要です。</p><p>この場合も、bodyがFutureを提供するときにflatMapが使用されます。そして、flatMapとmap全体が常にFutureになることを学びました。これによりuser.save(on:req).map {…}が返されることがわかります。これは、これが全体としてflatMapを前もって使用する必要があることを知っているFutureになるためです。</p><p>リダイレクトは未来を返さないため、次の手順は簡単です。そのため、ここでは前もって地図を使用します</p><blockquote>将来の価値にアクセスするには、mapまたはflatMapが必要です。マップ関数内の戻り値が将来ではない場合は、mapまたはflatMapを使用します。</blockquote><p>cmd + rを実行するか、プロジェクトを実行してブラウザでサイトを起動すると、新しいユーザーを作成し、その際にリストを拡大することができます</p><blockquote>注:インメモリデータベースを使用しているため、再実行後にすべてのデータが失われます</blockquote><h4>10.ここからどこへ行くか</h4><p>Githubでサンプルプロジェクトを含むすべてのチュートリアルのリストを見つけることができます:<br />https://github.com/vaporberlin/vaporschool</p><h4>私の記事を読んでくれて本当に嬉しいです!何か提案や改善があれば教えてください!私はあなたから聞いてみたいです! </h4><img alt="" src="https://imgstore.nyc3.cdn.digitaloceanspaces.com/ceadesc/1568900871725.png" /><img alt="" src="https://imgstore.nyc3.cdn.digitaloceanspaces.com/ceadesc/1568900872652.png" /><img alt="Twitter / Github / Instagram" src="https://imgstore.nyc3.cdn.digitaloceanspaces.com/ceadesc/1568900873384.png" /></div><ins data-zxname="zx-adnet" data-zxadslot="ZX-SMR53" data-zxw="970" data-zxh="250" data-overlay="true"></ins><div class="neighbor-articles"><h4 class="ui header">こちらもご覧ください</h4><a href="/article/active-mindset-vs-passive-mindset-how-to-control-your-destiny-74fb0d/" title="アクティブマインドセットとパッシブマインドセット:運命をコントロールする方法">アクティブマインドセットとパッシブマインドセット:運命をコントロールする方法</a><a href="/article/real-guns-as-controllers-how-to-bring-anything-into-vr-93b76e/" title="コントローラーとしての本物の銃:VRにあらゆるものを持ち込む方法">コントローラーとしての本物の銃:VRにあらゆるものを持ち込む方法</a><a href="/article/how-to-trick-yourself-into-getting-the-writing-done-8f36da/" title="ライティングを完成させる方法">ライティングを完成させる方法</a><a href="/article/icos-explained-what-are-they-and-how-to-invest-wisely-b85690/" title="ICOの説明—それらは何であり、賢く投資する方法">ICOの説明—それらは何であり、賢く投資する方法</a><a href="/article/how-to-instantly-turn-around-an-employee-who-is-displaying-a-poor-attitude-and-a-lack-of-motivation-b1a209/" title="悪い態度とモチベーションの欠如を示している従業員を即座に好転させる方法">悪い態度とモチベーションの欠如を示している従業員を即座に好転させる方法</a></div></main><div class="push"></div></div><footer><div class="flags-footer"><a href="https://vi.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="vn flag"></i></a><a href="https://uk.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="ua flag"></i></a><a href="https://tr.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="tr flag"></i></a><a href="https://th.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="th flag"></i></a><a href="https://sv.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="ch flag"></i></a><a href="https://sr.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="rs flag"></i></a><a href="https://sl.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="si flag"></i></a><a href="https://sk.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="sk flag"></i></a><a href="https://ru.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="ru flag"></i></a><a href="https://ro.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="ro flag"></i></a><a href="https://pt.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="pt flag"></i></a><a href="https://pl.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="pl flag"></i></a><a href="https://de.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="de flag"></i></a><a href="https://ar.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="sa flag"></i></a><a href="https://bg.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="bg flag"></i></a><a href="https://cs.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="cz flag"></i></a><a href="https://da.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="dk flag"></i></a><a href="https://el.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="gr flag"></i></a><a href="https://ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="es flag"></i></a><a href="https://et.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="ee flag"></i></a><a href="https://fi.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="fi flag"></i></a><a href="https://fr.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="fr flag"></i></a><a href="https://hi.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="in flag"></i></a><a href="https://hr.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="hr flag"></i></a><a href="https://hu.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="hu flag"></i></a><a href="https://id.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="id flag"></i></a><a href="https://it.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="it flag"></i></a><a href="https://ko.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="kr flag"></i></a><a href="https://lt.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="lt flag"></i></a><a href="https://lv.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="lv flag"></i></a><a href="https://ms.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="my flag"></i></a><a href="https://nl.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="nl flag"></i></a><a href="https://no.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="no flag"></i></a><a href="https://uz.ceadesc.org/article/tutorial-how-to-write-models-using-fluent-ae42fd/"><i class="uz flag"></i></a></div>ceadesc.org<!-- --> © <!-- -->2020<!-- --> </footer></div></div></div></body></html>