Node.js
loopback
exercise
Node.jsDay 11

Loopbackでコード1行も書かないでAPIができた

More than 3 years have passed since last update.


はじめに

はじめてまして、@chocopie116です。渋谷の会社で働いています。

この投稿は、node.js2014のAdvent Calendarの11日目です

さて今回は、loopbackについて書いてみようと思います。


モチベーション

Node学園2014でStrongLoopのIssacさんからこのケーブルもらい、毎日ケーブルを使っています。

スクリーンショット 2014-12-11 3.17.55.png

ただケーブルを見る度に、loopback・・・loopbackと文字通りloopbackがループバックしていて、いつか使ってみなくてはと思っていていいタイミングなので使ってみようと思います。

僕自身Node.jsをさわりはじめて半年ぐらいです。仕事では使っていません。

最初はsocket.ioを使ってみたくて始めたのですが、npmのエコシステムすごいなーと思い、遊びのプロジェクトとかの機会に少しずつnode.jsを触っている感じです。

なんとかnode.jsのアーキテクチャだからこそできる部分を見つけて、お仕事で使えないかな―と目論見つつ、micro servicesのフレームワークのgraftでネタを考えようとしたのですが、それは今度時間のある別の機会にしようと思います!


loopbackとは?

loopbackとはStrongLoopというBaaSを運営する会社が、インフラだけじゃなく、フレームワークとして提供するフレームワークです。

モデルを生成して、自動でREST APIが生成したりと、コンテキストによっては結構使えそうな感じがするので試しに使ってみました。

loopbackとしては、Web、Mobile Appのバックエンドとして使ってくれ!みたいな感じでクライアントサイドSDKも提供しています。


Exercise

さて今回は、loopbackを使って、簡単にバックエンドAPIをつくるのを試してみようと思います。


お題

今チラッと積読本が目に入って苦しい重いをしたので、図書館の貸出システムのバックエンドをつくることを想定してモデリングして、APIを作成してみたいと思います。


ユースケースの一例


  • ユーザーはiPhone等のスマートフォンで会員登録することができる。

  • ユーザーはスマートフォンで本のタイトルからどこの図書館にあるかを探すことができる。

  • ユーザーはある図書館の本を予約することができる。

  • 司書はスマートフォンを使って、ユーザーのスマートフォンのマイページ(バーコードとか)を画面を撮影して、本の貸出を行うことができる


モデリング

ざっと登場するモノはこんな感じでしょうか

言葉の定義とか間違ってたらまさかり(うわーなにwあwせdrftgyふじこlp


  • Library (図書館)

  • Book (本)

  • Librarian (図書館で働いてる人)

  • User (図書館利用者)

  • StoredBook (図書館にある本)

  • Lease (本の貸出)

  • Reservation (本の予約)

Relationはこんな感じでしょうか

modeling.jpeg

きっと他にも見えていない必要なmodelもあるかとは思いますが、今回は、本を探してそれがどこの図書館にあるのか調べることができるというユースケースに絞ってAPIを創ってみようと思います。


セットアップ

まずはコマンドラインツールを入れましょう。globalに入れます。ちなみにインストールに結構時間がかかるので、コマンド叩いたらゴハン食べてお風呂入るぐらいの勢いでもいいかもしれませんw

$ npm install -g strongloop

$ mkdir loopback-exercise

$ cd loopback-exercise
$ slc loopback

Yeomanで登録されているgenerator経由で、projectのひな形が作成されます。


loopback-explorer

loopbackはモデル(json schema)を定義すると簡単にREST APIが作成されます。

そしてそのREST APIをGUIで触れるツールがlooback-explorerです。

まずはprojectのrootで下記のコマンドをたたいてアプリケーションを起動してみましょう。

$ slc run

GET /explorer

スクリーンショット 2014-12-10 23.34.35.png

画面でてきた。

デフォルトだと

Userモデルに対するAPIがたくさんあります。

スクリーンショット 2014-12-10 23.34.47.png

こりゃすごいw


実際にモデルを作成してみます


では自分でモデルを作成してみます。

➜  loopback-exercise git:(master) slc loopback:model

? Enter the model name: Library # 作成するモデルの名前
? Select the data-source to attach Library to: db (memory) # storeの方法
? Select model's base class: PersistedModel # どのクラスを継承するか。
? Expose Library via the REST API? Yes # REST APIの自動生成
? Custom plural form (used to build REST URL): Libraries # 複数形.(defaultだとmodel nameに's'がつくだけ)
Let's add some Library properties now.

Enter an empty property name when done.
? Property name: id # プロパティ名
invoke loopback:property
? Property type: number # 型
? Required? Yes #必須か

Let's add another Library property.
Enter an empty property name when done.
? Property name: name
invoke loopback:property
? Property type: string
? Required? Yes

Let's add another Library property.
Enter an empty property name when done.
? Property name:

ひと通り必要そうなモデルも一気につくってしまいます。

アプリケーションを再起動して、再度explorerを見てみます。

slc run

スクリーンショット 2014-12-11 1.41.45.png

お、見えましたね

ちなみに/explorer/resourcesをひらくと、APIの一覧が見れます

各モデルに対してCRUDのWEB APIが既に用意されているのでWEB側の管理画面とかつくるのもclient sideのJavaScriptとかで簡単にできそうですね。


モデルのリレーションを定義してみます

$  loopback-exercise git:(master) slc loopback:relation

? Select the model to create the relationship from: Book #本は
? Relation type: has many #複数もっています
? Choose a model to create a relationship with: StoredBook #貯蔵本
? Enter the property name for the relation: storedBooks #関係の名前
? Optionally enter a custom foreign key: book_id #外部キーのカラム名
? Require a through model? No


APIをたたいてみる

アプリを再起動して、テストデータを入れる

$ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"title": "test_book_1", "author":"test-king", "isbn":"isbn-xxx1"}'  http://192.168.56.110:3000/api/books/

$ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"title": "test_book_2", "author":"test-king", "isbn":"isbn-xxx2"}' http://192.168.56.110:3000/api/books/
$ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"title": "test_book_3", "author":"test-king", "isbn":"isbn-xxx3"}' http://192.168.56.110:3000/api/books/

$ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"library_id":1, "book_id":1}' http://192.168.56.110:3000/api/storedbooks/
$ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"library_id":2, "book_id":1}' http://192.168.56.110:3000/api/storedbooks/

$ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"name":"test_library_1"}' http://192.168.56.110:3000/api/libraries/


クライアントサイドの気持ちになってAPIを叩いてみる


  • GET /api/books

    スクリーンショット 2014-12-11 3.12.12.png


  • GET /api/books/?filter={"where":{"title":"test_book_1"}}

    スクリーンショット 2014-12-11 3.12.30.png


  • GET /api/books/1/storedbooks

    スクリーンショット 2014-12-11 3.12.54.png


  • GET /api/libraries/1

    スクリーンショット 2014-12-11 3.13.14.png


今回はmodelもrelationもgeneratorのコマンドを使って手抜きで定義しましたが、コマンド1つでモデル感のリレーションを定義するだけで、アプリのバックエンドのAPIができちゃうのに驚きです。

改めてgithubのdiffを見てみると驚きの記述量ですw


まとめ

実際にアプリケーションをつくるには、永続化(DB)をするとは思うのですが、dataSourceを定義して、自分の使いたいdatabase driverのAdapterを使えば簡単にoracle,mysqlやmongo等に永続化できます。expressをベースとしてはいるものの機能としてリッチにした分、抽象化されているところが多々あって最初の学習コストはかかりますが、要件によってはかなりスピーディーに開発出来ると思いました。


大反省

なんと2日前に同じloopbackのネタで書いてくださっていたgologo13さんと内容がだいぶかぶってしまっていました。

ちなみに僕のブログはIt's now or neverなのですが、

驚くことにgologo13さんとブログタイトルもかぶっていましたw

いろいろかぶってしまってすみませんm(_ _)m

明日はkoki_cheeseさんがRasberry Pi関連の投稿だそうです。最近Beaconを手に入れたので、個人的にとても楽しみです。