CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
7/2にRails3.2.19、4.0.8及び4.1.4がリリースされました(*1)(*2)。このリリースはPostgreSQL利用時におけるSQLインジェクションのセキュリティフィックスですので(*3)、できるだけ早くアップデートすることをお勧めいたします。
さて話は変わりますが筆者はここ数ヶ月、お仕事でJavaを使ったプログラミングをしています。Javaそのものは5年くらい前に触ったきりでその時はJava6だったのですが、今ではJava8までリリースされています。枯れた技術と言われることもありますがいろんな試みを取り入れながら進化しており、きちんとアンテナを張っていないと取り残されていくなあと実感しました。
JavaEEに関してもJ2EEの重厚すぎるイメージを持っていましたが、最新の物ではかなりコンパクトに洗練されているみたいです。そんなJavaEEのなかで個人的にいいなと感じたものがJAX-RS(*4)です。
JAX-RSは「Java API for RESTful Services」の略で、その名の通りRESTfulな(Web)サービスを作るためのJava標準APIです。このAPIはアノテーションをベースとして、あるメソッドの処理とリクエストURL、HTTPメソッドを対応付けるため、直感的にRESTfulなWebサービスを開発することができます。
Rubyでも似たようなものはないかと探したところ、Grape(*5)というライブラリがありましたので今回と次回、2回に分けてこちらをご紹介していきます。
GrapeとはRESTfulなWebAPIを構築するためのライブラリです。前述の通りRubyで書かれており、Rackアプリケーションであれば簡単に動作させることができます。また軽量で直感的なライブラリでもあるため、学習コストもそれほどかからず既存のアプリケーションにも組み込みやすいかと思います。
ここでは郵便番号検索APIの実装をしていきながら、Grapeについてご説明いたします。
なお、動作環境は以下の通りです。(*6)
また実装する郵便番号検索APIはごくごく簡単なもので、「/zip/:zip_code」にGETリクエストを行うと:zip_codeに対応する郵便番号をJSON形式で返すというものにします(*7)。
まずはインストールを行いましょう。Gemfileに以下を追記し、「bundle install」を実行します。
gem 'grape'
インストール後、以下の手順で郵便番号検索APIを実装していきます。
まずモデルを生成します。
> rails g model zip zip_code:string address:string invoke active_record create db/migrate/#{yyyymmddssssss}_create_zips.rb create app/models/zip.rb (略)
その後以下のコマンドを実行し、テーブルも作成します。
> rake db:migrate
さらに初期データとしてデータを投入しておきましょう。以下を「test/fixtures/zips.xml」に記述します(*8)。
one: zip_code:100-1701 address: 東京都青ヶ島村 two: zip_code: 100-0301 address: 東京都利島村
記述後、以下のコマンドを実行します。
> rake fixture:load
ここからがGrapeを利用したソースコードの実装となります。appフォルダ以下にapiというフォルダを作成し、ここにAPI部分のファイルを格納することとします。
「app/api/zip_api.rb」を作成し、以下のように編集します。
class ZipAPI < Grape::API format :json get "zip/:zip_code" do zip = Zip.where(zip_code: params[:zip_code]).first if zip zip.to_json end end end
GrapeではRailsと異なり、ルーティング定義と対応する処理とをブロック付きメソッド呼び出しの形で定義します。呼び出すメソッド名がHTTPメソッドとなり、第一引数にリクエストURL、ブロックには対応する処理を記述します。
上記のソースコードをRailsで書き直すと以下のようになります。
# routes.rb get "zip/:zip_code" => "zip#show", format: false # コントローラ class ZipsController < ApplicationController def show zip = Zip.where(zip_code: params[:zip_code]).first if zip json = zip.to_json end render text: json end end
リクエストURLには「:(コロン)」をつけることで、Railsのルートパラメータのように扱うことができ、ここではparamsメソッドでその値を取得しています(*9)。
このソースコードで利用している特筆すべきメソッドについて、以下に一覧を示します。
メソッド | |
format(new_format=nil) | APIのレスポンスフォーマットを設定する。(初期値はXML) [new_format] フォーマットを指定(:xml, :json, :txtなど) |
get(paths=['/'], options={}, &block) | 引数pathsへのGETリクエストに引数&blockの処理を対応付ける。(postやput、deleteなども有) [paths] 対応するリクエストURLを指定(配列で複数指定することも可能) [options] 引数pathsとマッチするための条件を指定 [block] 対応する処理を定義 |
params | リクエストパラメータを取得する。 |
ここまでできましたら、一度動作確認を行ってみましょう。そのためにRailsアプリケーション上へデプロイを行います。デプロイの手順は大きく2つ、Railsへのパス追加とルーティング定義へのマウントです。
Railsへのパス追加は「config/application.rb」内のApplicationクラス定義内に、以下を追加します(*10)(*11)。
config.paths.add File.join("app", "api"), glob: File.join("**", "*.rb") config.autoload_paths += Dir[Rails.root.join("app", "api", "*")]
ルーティング定義へのマウントは「config/routes.rb」に以下を追加します(*12)。
mount ZipAPI => "/"
編集が完了しましたら、「rails s」でWEBRickを起動し動作確認をしましょう。URLをアドレスバーに入力して確認してもいいですが、ここではAPIらしく開発者ツールのコンソールよりXMLHttpRequestを利用してアクセスしてみたいと思います。以下のJavaScriptをコンソール上で実行します。
var xhr = new XMLHttpRequest; xhr.open("get", "http://localhost:3000/zip/100-1701"); xhr.addEventListener("load", function(){ console.log(this.responseText); }); xhr.send();
返送されるJSON自体はActiveRecord#to_jsonメソッドの出力をそのまま使っているため何とも微妙ですが、一応動くことは確認できたかと思います。
今回はGrapeの簡単な紹介として、郵便番号検索APIを実装してみました。次回はこのAPIに追加や削除の機能を盛り込みながら、もう少し詳しくGrapeをご紹介していきたいと思います。
それでは、Enjoy Ruby!
*1 : http://weblog.rubyonrails.org/2014/7/2/Rails_4_0_8_and_4_1_4_have_been_released/
*2 : http://weblog.rubyonrails.org/2014/7/2/Rails_3_2_19_4_0_7_and_4_1_3_have_been_released/
*3 : 正確にはRails4.0.8及び4.1.4は、当該セキュリティフィックスを行ったRails4.0.7及び4.1.3のリグレッションフィックスです。
*4 : https://java.net/projects/jax-rs-spec
*5 : http://intridea.github.io/grape
*6 : ここではRailsアプリケーション上でGrapeを動かしますが、前述の通りRackアプリケーション上であれば簡単に動作させることができます。
*7 : ただし今回はJSONを整形することが主眼ではないため、ActiveRecord#to_jsonを使って出力を行っています。
*8 : ここではTest::Unitを前提としています。RSpecなどでfixtureファイルの場所が異なる場合には適宜読み替えてください。
*9 : paramsメソッドはRails同様に扱うことができます。
*10 : ここでは前述の手順通り「app/api」以下にGrapeのファイルを格納しているものとして記述しています。格納場所を変える場合には適宜変更してください。
*11 : Grapeのドキュメントにはこの手順が必要であると書いてありますが、「app」以下のサブディレクトリは自動でロードされていた気がするので不要かもしれません(現に手元の環境では記述なしでも動作しました)。
*12 : ここではルート直下にマウントしていますが、他のURLとのバッティングを考慮すると適切なパスプレフィックスをつけるべきだと思います。
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes