はじめに
静的ページの表示に続いて動的ページの表示をしてみました。全件表示ですがひとまず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
で情報入力のためのフォームを呼び出せます。
ドキュメントを登録する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
としているため、この時点で対応付けられるデータモデルの特定ができています。
動かしてみよう
元の状態
デザインもへったくれもないですね……
追加してみよう
localhost:8080/newにアクセスし、適宜入力してみます。
入力できたら登録するボタンをポチッとな。
APIの都合上、追加した本の情報が返ってきて表示されています。
追加できているかどうか確認してみる
無事追加されています。
まとめ
web上で入力した本の情報をDBに追加することができました。webアプリケーションぽくなってちょっと楽しい。
なお、既存のAPIをそのまま流用してしまったので、登録するボタンを押した後、追加したデータが返ってきてしまっています。データを返すのではなく、一覧のViewを返すように戻り値を調整したりすると見栄えがよくなると思います。