RailsのAPIモードを試してみた話
RailsのAPIモードを試してみた話
はじめに
これは香川大学工学部サークルSLPのアドベントカレンダー14日目の記事です。 前後、怖い人に挟まれていますが頑張ります(ガクブル)。 今回はRails5から実装されたAPIモードを使ってAPIサーバを構築し、様々な言語でHTTPリクエストを送ってみたいと思います。 かなり緩くやっていけたらなと思います。
APIモードとは
API作成に特化したモードのことで、Rails5で実装された機能らしいです。 簡単に今までのRailsとの違いを説明すると、MVCでいう、Viewの部分が存在しません。 変わりにそのURLにアクセスするとerbを返さず、jsonを返す仕様になっています。 また、標準で入っているGemもViewの分が必要なくなっているので、普通に立ち上げたRailsのプロジェクトよりも少なくなっています。 詳しくは各々で調べてみてください。
とりあえず使ってみた
さっそくですが、RailsのAPIモードを使って、APIサーバを構築してみたいと思います。 今回は名前と学籍番号を管理するAPIを構築してみます。
今回使用した開発環境をざっくり紹介するとこんな感じです。
- Ubuntu16.04
- Ruby 2.4.1
- Rails 5.1.4
それではまず、プロジェクトを立ち上げます。
Rails new name_api --api
プロジェクト名の後に、 --api
をつけることでAPIモードでプロジェクトが立ち上がります。
--api
をつけなければ今まで通りのRailsのプロジェクトとして立ち上がります(当たり前)。
では、プロジェクトの中に入ってみましょう。
cd name_api
Railsらしく、様々なディレクトリとファイルが生成されていると思います。 今回は手早くRESTfulなAPIを作りたいのでscaffoldを使います。 基本的にはAPIモードでもRailsのコマンドは同じように使えるみたいです。 それでは、コマンドを入力していきます。
rails g scaffold User name:string number:string
ずらーっと色々と表示されたと思います。createとかinvokeとかrouteが出てきて、正常に終わっていればOKです。 私側の実行では、以下のように表示されました。
Running via Spring preloader in process 19815 invoke active_record create db/migrate/20171205074009_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml invoke resource_route route resources :users invoke scaffold_controller create app/controllers/users_controller.rb invoke test_unit create test/controllers/users_controller_test.rb
そしてmigrateします。
rails db:create && rails db:migrate
これでAPI側の実装はほとんど終わりです(すごく簡単!!)。 それではサーバを立ち上げてみましょう。
rails server -b=0.0.0.0
無事に起動したら、アクセスしてみます。
http://localhost:3000
アクセスできたら、いつものRailsのページが表示されると思います。
ルーティングを確認
以下のコマンドを入力して、ルーティングを確認します。
rails routes
以下のように表示されていると思います。
Prefix Verb URI Pattern Controller#Action users GET /users(.:format) users#index POST /users(.:format) users#create user GET /users/:id(.:format) users#show PATCH /users/:id(.:format) users#update PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy
ためしに、users#indexにアクセスしてみます。
http://localhost:3000/users
通常、scaffoldを使うとあらかじめ完成されたページが表示されると思います。しかし、今回の場合だと、 [ ] だけが表示されたと思います。 なぜかというと、controllerを見ればわかりますが、APIモードでは、erbではなく、JSONを返してくれているからなのです。 [ ] なのは、まだ何もレコードされていないからですね。
様々な方法でPOSTしてみる
それでは、このAPIにPOSTリクエストを送ってみます。 基本的にはHTTPリクエストで、JSONをPOSTしてあげればOKです。 POSTするURLは先ほど確認したのでそれに従います。 今回の場合であれば以下のURLにPOSTしてあげればよさそうです。
http://localhost:3000/users
curlでPOST
curl -X POST -H "Content-Type: application/json" -d '{"name": "明示カール", "number": "17t200"}' http://localhost:3000/users
RubyでPOST
post.rb
require 'net/http' require 'uri' require 'json' url = "http://localhost:3000/hoges" sample_data = {"name": "白沢ルビィ" : "number": "16t200"} uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) req = Net::HTTP::Post.new(uri.request_uri) req["Content-Type"] = "application/json" req.body = sample_data.to_json res = http.request(req)
Python3でPOST
post.py
import requests import json url = 'http://localhost:3000/hoges' method = "POST" obj = {"name" : "本田パイソン", "number": "15t200"} json_data = json.dumps(obj).encode("utf-8") response = requests.post(url, json.dumps(obj), headers = {'Content-Type' : 'application/json'}) print(response.text)
JavaScriptでPOST
JavaScriptでPOSTする場合API側の設定を少し変更してあげなければなりません。 変更点は以下の記事を参考にしてみてください。 https://qiita.com/kaorumori/items/0a53c248343892c8f35c
index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JavaScriptからPOSTでJSONデータを送信する</title> <script src="jquery.js"></script> <script src="post.js"></script> </head> <body> <p> URL: <input type="text" id="url_post" name="url" size="100" value="http://localhost:3000/users"> </p> <p> name:<input type="text" id="name" size="30" value="じゃばすく太郎"> </p> <p> number:<input type="text" id="number" size="30" value="13T200"> </p> <p> <button id="button" type="button">Submit</button></p> </p> </body> </html>
post.js
$(function(){ $("#response").html("Response Value"); $("#button").click( function(){ const url = $("#url_post").val(); const JSONdata = { name: $("#name").val(), number: $("#name").val() }; alert(JSON.stringify(JSONdata)); $.ajax({ type : 'post', url : url, data : JSON.stringify(JSONdata), contentType : 'application/JSON', dataType : 'JSON', scritCharset : 'utf-8', succes : function(data) { alert("success"); alert(JSON.stringify(data)); $("#response").html(JSON.stringify(data)); }, error : function(data) { alert("error"); alert(JSON.stringify(data)); $("#response").html(JSON.stringify(data)); } }); }); });
今回のサンプルコードでは、jqueryを使用しました。 今回の場合ですと、jqeuryをjquery.jsとして同じ階層のディレクトリに置いておいてあげて解決しています。
POSTしたデータを確認してみる
それでは先ほど、POSTしたデータを確認してみましょう。 まずはすべてのPOSTしたすべてのデータを確認してみます。
http://localhost:3000/users
上記のURLにアクセスすると、先ほどと違いPOSTした内容がレコードされていると思います。 せっかくなのでGETリクエストを送ってデータを取得してみます。 今回は、手っ取り早くcurlを使います。
curl http://localhost:3000/users
取得したのがこちら。
[{"id":1,"name":"明示カール","number":"17t200","created_at":"2017-12-05T08:15:37.735Z","updated_at":"2017-12-05T08:15:37.735Z"},{"id":2,"name":"白沢ルビィ","number":"16t200","created_at":"2017-12-05T14:51:40.472Z","updated_at":"2017-12-05T14:51:40.472Z"},{"id":3,"name":"本田パイソン","number":"15t200","created_at":"2017-12-05T14:52:46.918Z","updated_at":"2017-12-05T14:52:46.918Z"},{"id":4,"name":null,"number":"じゃばすく太郎","created_at":"2017-12-05T15:00:04.685Z","updated_at":"2017-12-05T15:00:04.685Z"}]
created_atやupdated_atは違う値を保持しているはずですが、似たようなデータを取得できたと思います。 次にレコードしたデータを一つずつ取得してみます。 試しに1番目と2番目のデータを取得してみます。 1番目
curl http://localhost:3000:users/1
{"id":1,"name":"明示カール","number":"17t200","created_at":"2017-12-05T08:15:37.735Z","updated_at":"2017-12-05T08:15:37.735Z"}%
2番目
curl http://localhost:3000:users/2
{"id":2,"name":"白沢ルビィ","number":"16t200","created_at":"2017-12-05T14:51:40.472Z","updated_at":"2017-12-05T14:51:40.472Z"}%
いい感じに取得できました。
まとめ
雑な説明になってしまいましたがいかかだったでしょうか。 いろいろな部分の説明を省いているので、詳しく知りたい方はこの記事ををきっかけにAPIモードについて調べてもらえたらなと思います。 私自身は、今後このモードを使って、様々なAPIを作ってみて、それに対応したネイティブアプリやスマホアプリを作ってみたいです。
最後に・・・
この記事で作ったサンプルコードの出来が悪くても、多めにみてやってください...。