こんにちは。ikedaです。
今回は、簡単なapi wrapperのgemを作りたくて調べていたところ、gem Faradayを知ったのでこちらの紹介とgemでどう実装したのかを書きたいと思います。
gem Faraday
faradayは, HTTP Clientの操作をより簡易的に扱えるgemで, adapterとしても様々なライブラリが利用できます。私が利用するのはrubyの標準ライブラリに含まれているNet::HTTPをadapterとします。
READMEをみてもらうとまず書いてありますが、こちらになります
Faraday is an HTTP client lib that provides a common interface over many adapters (such as Net::HTTP) and embraces the concept of Rack middleware when processing the request/response cycle.
実装について
githubのapiを利用してgithubに登録している公開鍵をローカルに保存するgemを開発しているときに、apiをたたく機能をfaradayで実装しました。
gemはすでにrubyGemsに公開していますが、まだ修正を頻繁にかけています。リポジトリはこちら
まだまだ開発不足*1があると思いますが、ご理解ください。
それではこのgemをもとにgem faradayの実装の話を進めていきます。
私が書いた実装部分
gem faradayを実装した部分は下記です。
# coding: utf-8
require 'faraday'
require 'faraday_middleware'
module GetGithubPubKeys
module Connection
def self.new( options = {} )
Faraday.new( url: 'https://api.github.com' ) do |faraday|
faraday.request :url_encoded
faraday.request :json
faraday.response :json, :content_type => /\bjson$/
faraday.response :logger
faraday.adapter Faraday.default_adapter
end
end
end
end
実装はこれだけです。
Faradayのコード
Faraday.newのコードをさらに追っていくと下記のようになっていきます。
* 筆者が確認したときにはbranch master commit log 2014/05/04に最終コミット日でした
(紹介する部分を抜粋して記述しています。)
module Faraday
class << self
# url - The optional String base URL to use as a prefix for all
# requests. Can also be the options Hash.
# options - The optional Hash used to configure this Faraday::Connection.
# Any of these values will be set on every request made, unless
# overridden for a specific request.
# :url - String base URL.
# :params - Hash of URI query unencoded key/value pairs.
# :headers - Hash of unencoded HTTP header key/value pairs.
# :request - Hash of request options.
# :ssl - Hash of SSL options.
# :proxy - Hash of Proxy options.
#
# Examples
#
# Faraday.new 'http://faraday.com'
#
# # http://faraday.com?page=1
# Faraday.new 'http://faraday.com', :params => {:page => 1}
#
# # same
#
# Faraday.new :url => 'http://faraday.com',
# :params => {:page => 1}
#
# Returns a Faraday::Connection.
def new(url = nil, options = nil)
block = block_given? ? Proc.new : nil
options = options ? default_connection_options.merge(options) : default_connection_options.dup
Faraday::Connection.new(url, options, &block)
end
end
end
コメントも含めて転記しましたが、newメソッドでblockが与えられていればProc.newを代入します。
Faraday::Connection#initializeのほうも見ていきます。
module Faraday
class Connection
def initialize(url = nil, options = nil)
...
yield(self) if block_given?
end
end
selfを返していますので。呼び出された自分自身のインスタンスが返されますので、これでFaraday::Connectionのインスタンスが返されます。
先ほどのコードにもどります。
Faraday.new( url: 'https://api.github.com') do |faraday|
faraday.request
faraday.request :url_encoded
faraday.request :json
faraday.response :json, :content_type => /\bjson$/
faraday.response :logger
faraday.adapter Faraday.default_adapter
と書いており、上記の通り|faraday|にはFaraday::Connectionインスタンスが渡されます。
名前でなんとなくわかるように思えますが、request, responseでオプションを与えていてresponse :jsonで、response.bodyのjson形式の文字列をHash形式にしてくれます。
ただしこの実装はFaradayではなく、gem faraday_middleware利用して実装していますので
コードを見たい方は、こちらへどうぞ
parseできるのはjsonだけではなく、デフォルトではString、指定すればxmlなども可能です。
adapterはFaraday.default_adapterにすると:net_httpが返されてNet::HTTPが利用されます。
以上でfaradayの実装のお話は終わりです。
なお、さらっと流してしまいましたが、faraday_middlewareを使うことで、oauthへの対応も可能になりますのでREADMEを読んでおくと余計なコードの記述を減らそうです。
rubyの標準ライブラリのNet::HTTPなどを、そのまま利用する方も多いようなのでご紹介しました。
*1 (READMEにも書きましたが、テスト、機能、英語によるコメントなどが不足していると思いますので自分のモチベーションが続けば更新していきたいと思います。)