LoginSignup
1
0

More than 3 years have passed since last update.

ORMを使用してAPIを作る (Kitura/ PostgreSQL)

Last updated at Posted at 2019-09-15

はじめに

この記事ではIBM製のSwiftでサーバーサイドを実装することのできるフレームワークのKituraを使用してRESTful APIを作成するときの大まかなポイントをまとめていきます。ハンズオンではないです。

今回は、PostgreSQLのORMを併用してデータを保存と取得ができるAPIを作る想定で進めていきます。

今回使用するライブラリのうち、自分で追加する必要のあるライブラリ

ライブラリ名 バージョン
SwiftKueryORM 0.6.1
SwiftKueryPostgreSQL 2.1.1

Model

まずは、永続化するモデルの定義から。

SwiftKueryORMにはModelというプロトコルがあり、それに準拠してモデルを作成します。ModelはCodableに準拠しています。

また、var id: Int?と記述しておくと、idがnilの場合に自動でidを振り与えてくれるらしいです。注意としては、手動でもidを設定することができるのでそのidがもう既に存在していないかは保存する前に確認した方が良いようです。

// id以外のプロパティは適当です。
struct Diary: Model, Equatable {
    var id: Int?
    var title: String?
    var content: String?
    var posterName: String?    
    var likedCount: Int?
    var createdAt: Date?
    var updatedAt: Date?
}

このあと、PostgreSQLをインストールしたり、Terminal上で

createdb データベース名

などを叩いて、初期の設定しなければならないのですが今回は省略します。

それでは、本題に入ります!

GET

KituraはRouterというクラスを使用してルーティングを設定します。Appクラスからプロパティとして取得できるのでそれを使用します。

app.router.get("/api/v1/diary/read") { (request, response, next) in   
}

getメソッドの第一引数はルーティングを指定します。この場合、ローカル環境なら http://localhost:8080/api/v1/diary/readにアクセスすればコールバックが呼ばれます。

もしクエリパラメータ ?id=1234 みたいなものを取得したい場合は、request.queryParametersで取得できます。

let id = request.queryParameters["id"]

READ (PostgreSQL)

GETリクエストを受け取ったら全件取得をします。
ORMを使用して非常に簡潔にかけます。
取得したいエンティティクラスから.findAllメソッドを呼ぶだけです。例えば、上のDiaryモデルとして保存したデータを取得したい場合は

Diary.findAll { (diaries: [Diary]?, error: RequestError?) in
}

このような感じで取得することができます。

まとめると、

app.router.get("/api/v1/diary/read") { (request, response, next) in   
    Diary.findAll { (diaries: [Diary]?, error: RequestError?) in
        guard let diaries = diaries else { return next() }
        response.send(diaries)
        next()  
    }
}

これで、データを取得してレスポンスで返せると思います。

POST

postは初見でやったときは結構はまりました。。。まとめにも記載しますが、Codable Routingを使用しないでrequest.body?.asRawでData型を取得するにはミドルウェアを指定する必要があるようです。

app.router.post("/api/v1/diary/create", middleware: BodyParser())

このBodyParser()によって、送られてきたBody部分を適切なプロパティに流してくれるのだと僕は考えています。

Note: If you have not declared a Content-Type header, ParsedBody will be nil.
引用: https://ibm-swift.github.io/Kitura/Classes/BodyParser.html

ただ、リクエスト時にContent-Typeを指定しないとBody部分はnilになってしまうので注意です。

また、今回はCodableなので、asRawプロパティにアクセスします。

app.router.post("/api/v1/diary/create") { (request, response, next) in
    guard let data = request.body?.asRaw else {
        return next()
    }
    guard let diary = try? JSONDecoder().decode(Diary.self, from: data) else {
        return next()
    }    
}

上のような流れで、送られてきたBody部分をDiaryモデルにデコードしています。

CREATE (PostgreSQL)

KueryORMがsaveメソッドを用意してくれているのでそれを使いましょう。

// 本当は、保存する前に、idがユニークなものかを確認した方が良いです。。。
diary.save() { (diary: Diary?, error: RequestError?) in
    if let error = error {
        print(error) 
        return next()
    }
    guard let diary = diary else {
        return next()
    }
    response.send(diary)
}
POSTリクエストの一連の流れ.swift
app.router.post("/api/v1/diary/create", middleware: BodyParser())
app.router.post("/api/v1/diary/create") { (request, response, next) in
    guard let data = request.body?.asRaw else {
        return next()
    }
    guard let diary = try? JSONDecoder().decode(Diary.self, from: data) else {
        return next()
    }    
    diary.save() { (diary: Diary?, error: RequestError?) in
        if let error = error {
            print(error) 
            return next()
        }
        guard let diary = diary else {
            return next()
        }
        response.send(diary)
    }
}

まとめ

今回は、

  • KituraでGETリクエスト・POSTリクエストをどのように行うのか。
  • KituraでORMを使用したときにどのような流れでデータの取得・保存を行うのか。

がなんとなくでも掴めていただけたらめちゃくちゃ嬉しいです。
自分もまだ分かっていない部分が多いので、もっとKituraに強くなりたいと思います。

ちなみに、Codable Routingを使用して書くともう少しスマートに書けるので別記事で紹介したいです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0