WebフォームからVaporアプリケーションを使ってドキュメントを追加してみる

MongoDB
WebフォームからVaporアプリケーションを使ってドキュメントを追加してみる

はじめに

静的ページの表示に続いて動的ページの表示をしてみました。全件表示ですがひとまずCRUDのR(Read)ができた状態ですね。今回はCRUDのC(Create)をやってみようと思います。

DBはMongoDBです。

情報を入力するためのフォームを用意する

フォームを作る

HTMLでフォームをゴリゴリっと作ります。静的ページ、動的ページの時と同じように、拡張子leafを付けたViewとしてAddBook.leafと保存しました。

<h1>Add Book</h1>
<form method="POST">
  <label>書名</label>
  <br>
  <input type="text" name="title" value="" placeholder="書名を入力">
  <br>
  <label>出版社</label>
  <br>
  <input type="text" name="publisher" value="" placeholder="出版社を入力">
  <br>
  <label>金額</label>
  <br>
  <input type="number" name="price" value="0">
  <br>
  <input type="submit" value="登録する">

見た目はこのような感じになります。

フォームができました

フォームで入力したものをDBへ保存するということに主眼を置いたため、CSSやフレームワークなどは使っていません。実際に運用する段になったときに装飾をしていきましょう。

アプリケーションからフォームを呼び出す

routes.swiftにrouteを追加します。静的ページを表示するのと同じ段取りです。

router.get("new") { req in
    return try req.view().render("AddBook")
}

これでlocalhost:8080/newで情報入力のためのフォームを呼び出せます。

Vaporアプリケーションからフォームを呼び出しました

ドキュメントを登録するAPIを用意する

もうできてます

これまでに作ったAPIを活用しましょう!

router.post(Book.self,at:"api/book") { (req, book) -> Future<Book> in
    let client = try! req.make(MongoClient.self)
    let collection = client.db("vaporapp").collection("books", withType: Book.self)

    return try req.content.decode(Book.self).map(to: Book.self) { book in
        _ = try! collection.insertOne(book)
        return book
    }
}

アプリケーションへ情報を渡せるようにする

入力した情報を先ほどのAPIへ渡します。そのためには、formタグのaction属性にAPIのパスを設定します。フルパスではなく、routes.swiftで作ったrouteのパスだけで良いです。

<form method="POST" action="api/book">

フォームで入力した値とDBのドキュメントとの関連付け

ふとした疑問。

フォームで入力された値はaction属性で指定したAPIに渡されるわけですが、Vaporアプリケーション側でDBのドキュメントとどうやって紐付けしているのか?

この紐付けは、inputタグのname属性にデータモデルのプロパティを指定することで実現できます。

例えば、書名ではname属性にtitleを指定しています。

<input type="text" name="title" value="" placeholder="書名を入力">

Vaporアプリケーション側でのデータモデルはこのようになっています。

struct Book: Content {
    var title: String
    var publisher: String
    var price: Int
}

このように、データモデルのプロパティと一致させておけば自動的に紐付けされます。

データモデルが複数あるときは?

ご心配なく。

呼び出すAPIにて

withType: Book.self

としているため、この時点で対応付けられるデータモデルの特定ができています。

動かしてみよう

元の状態

DBに登録されている本の情報(追加前)

デザインもへったくれもないですね……

追加してみよう

localhost:8080/newにアクセスし、適宜入力してみます。

適宜本の情報を入力しました

入力できたら登録するボタンをポチッとな。

追加された本の情報が返ってきました

APIの都合上、追加した本の情報が返ってきて表示されています。

追加できているかどうか確認してみる

最下行に入力した本が追加されています

無事追加されています。

まとめ

web上で入力した本の情報をDBに追加することができました。webアプリケーションぽくなってちょっと楽しい。

なお、既存のAPIをそのまま流用してしまったので、登録するボタンを押した後、追加したデータが返ってきてしまっています。データを返すのではなく、一覧のViewを返すように戻り値を調整したりすると見栄えがよくなると思います。