Net::HTTPをより簡単に利用できるgem Faraday

こんにちは。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にも書きましたが、テスト、機能、英語によるコメントなどが不足していると思いますので自分のモチベーションが続けば更新していきたいと思います。)

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

ikeda

業務系のエンジニアから2013年Web系エンジニアに転身して、2014年02月よりBPS株式会社に入社。

ikedaの書いた記事

開発
静的解析ツールgem RuboCop

2014年09月11日

開発
blockの利用例 Ruby

2014年07月11日

開発
jsCafe#20に参加してきました

2014年05月17日

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ