面倒なAPIアクセスをPryのカスタムコマンドで省略する

## 更新のおしらせ

本記事はWebPay gemのバージョン2系に即して記述しています。
その後、メジャーバージョンアップを行いました。

ほとんどの内容はそのまま利用できますが、メソッド名などが一部変更になっています。
最新の情報は[WebPay公式サイトのRuby APIドキュメント](https://webpay.jp/docs/api/ruby)を参照してください。

## APIアクセスの面倒

ウェブサービスのAPIを試しに叩きたいときに、Rubyの環境を前提とするとIRBやPryがとても便利です。
APIの仕様をコピペしながら、こういう風に動くのかと知り、その場で使い捨てにするには良いのですが、
実装を進めながらとか運用に入った場合にAPIを改めて叩きたいとか、軽く利用状況を把握したいという時には度々コマンドなんだったっけと調べ直す手間がなかなか煩わしいです。
もちろん、ちゃんとスクリプトなどに落としておいて、必要な情報はすぐに取得可能な状態を作っておくのが正しいお話です。

逆にサービスのAPIを提供している側がそこをアシストするようなアプリやスクリプトを提供するというのも手ですが、大々的に専用アプリを準備するのは優先度的に下と判断されて上場するまでリリースされないことが危惧されます。

そこでPryのカスタムコマンドで簡単に対話的なアプリをつくってみます。

## Pryのカスタムコマンド

Pryのカスタムコマンドは、PryのCLI上向けに独自のコマンドを定義することが出来ます。
既存のコマンド群もカスタムコマンドと同様に定義されており、引数（オプション）や前処理、後処理、シェルコマンドの実行など諸々のことが出来るようになっています。

- [pry/lib/pry/commands at master · pry/pry](https://github.com/pry/pry/tree/master/lib/pry/commands)

## WebPayの情報を簡易的に扱う対話的インタフェース

GUI（ブラウザ経由）が現状貧弱な[WebPay](https://webpay.jp)ですが、普段さっと課金や顧客の状態を把握、処理したい場面に遭遇することが多いです。
その度にPryやIRBを立ち上げて

```
[1] pry(main)> require ‘webpay’
=> true
[2] pry(main)> WebPay.api_key = ‘test_xxxxxxxxxxxx’
=> "test_xxxxxxxxxxxx"
[3] pry(main)> WebPay::Charge.all
```

と書き進めるのも、なかなか骨の折れる作業です。
しかもこの例だと戻り値のオブジェクトがだだ長くて、スクロールし直すのも憂鬱です。

そこで、そういった場面向けのカスタムコマンド群を書いてみました。
- https://gist.github.com/hmsk/8084235

```
$ ruby webpay-pry.rb
```
で実行することで利用することが出来ます。

カスタムコマンドを前面から作成してしまうと、Pry本来のコマンドや評価が全部潰されてしまうので、カスタムコマンド群を

```ruby
Pry::Commands.import webpay_commands
```

としてインポートする形を取りました。これで普通のPryの機能も概ね利用出来ます。

### 使用例

ちょっと使ってみます。

```
[hmsk@] $ ruby webpay-pry.rb
At first, set secret key with: key 'test_secret_xxxxxxxxxx'

Type 'help' to help. type 'exit' to terminate.

WebPay>
```

実行すると非公開鍵を教えろという通知とともに、WebPayと対話出来そうなコンソールが表示されます。

```
WebPay> key 'test_secret_XXXXXXXXXXXXXXXXXXX'
test_secret_XXXXXXXXXXXXXXXXXXX
initializing...
loaded...
WebPay>
```

指示通りにキーを渡すと何やら初期化処理を行っていると知らされます。この間に課金や顧客の情報を集めてきています。

```
WebPay> help
charges : show charges
charge num: show charges with page number
customers : show customers
customer num: show customers with page number
WebPay>
```

helpを請うと使えそうなコマンドが4つ表示されます。（Pryの元々のコマンドも使えますが、丸ごと上書きしています）

```ruby
WebPay> charges
[0] ch_b8Sf3H2ZC7Wq2jh 0yen,
[1] ch_9KagdU6KEgOu90t 400yen,
[2] ch_9Kacih8st9fd8kc 400yen,
[3] ch_9Ka0Q5gDQg8o4sU 400yen,
[4] ch_7Ga8sE0dU2Jf5MS 300yen,
[5] ch_7tMasQ88Q2XBffF 400yen,
[6] ch_5Ca7JD5r15J6g9a 400yen,
[7] ch_5Ca6Br6ZGak1bUv 400yen,
[8] ch_21cfllfyT9sK55a 400yen,
[9] ch_1X49LdePjcyf1WL 400yen,
[10] ch_0X82X8803f5P7XV 0yen,
[11] ch_0X85182yO8g654X 400yen,
[12] ch_g0hcMY5fm0thgKi 0yen, アイテムの購入
[13] ch_fW95bV0KD23H3C2 0yen, アイテムの購入
[14] ch_fW95kbdpHcnsfdr 0yen, アイテムの購入
[15] ch_fW95oj7AAckOgLH 0yen, アイテムの購入
[16] ch_g0h3Fj4ws08C4Vk 400yen, アイテムの購入
[17] ch_fxn00Zecbdin4FY 400yen, アイテムの購入
[18] ch_f8B9XF2UxbIccvY 1000yen,
[19] ch_exreSg4iM58s6nC 1000yen,
[20] ch_dWhdwK2Hf6fAdpO 1000yen,
[21] ch_dS98u83W23NQ5Rp 111yen,
[22] ch_dS96CvcLIeU4ety 320yen,
[23] ch_dS93KW42U08Jeg9 900yen,
[24] ch_dS9ftAanFcgHdIJ 1500yen,
[25] ch_dO12Z031Y0qr2Pu 1554yen, WEB DB PRESSの購入
[26] ch_dO1dTP25MfD36wV 400yen, アイテムの購入
[27] ch_dgZ03K5e182j4VD 1000yen,
[28] ch_d0tarWdMDdxm2nj 400yen, アイテムの購入
[29] ch_cFP6LP7CH5G4dwd 1000yen,
[30] ch_c4FfxUadj3iI9EM 1000yen,
[31] ch_btvesU0rz5YJ9f5 1000yen,
[32] ch_aSlaTe7LYdmDbgf 1000yen,
[33] ch_ad3diPfuj6kPd30 1000yen,
[34] ch_9BTfqO9vCfNk3Ae 400yen, アイテムの購入
[35] ch_9BT4Pv9jwdjG6bh 1000yen,
[36] ch_98Z8Cidycc2Uaga 1000yen,
[37] ch_98Z8Ci3ZN7yCdV3 1000yen,
[38] ch_7Kh2Ir59KdH6e5E 1000yen,
[39] ch_7Khbvs5fH3q9cZN 1000yen,
[40] ch_7Kh4qkgByaeF0wr 400yen, アイテムの購入
You can retrieve charge from above with: e.g. `charge 1`
WebPay>
```

`charges`とすると最近のものから順に課金の情報が表示されました。
最後の指示に従って、ひとつ課金を抽出してみます。

```ruby
WebPay> charge 3
=> #<WebPay::Charge:0x007f96cc149c58
 @attributes=
  {"id"=>"ch_9Ka0Q5gDQg8o4sU",
   "object"=>"charge",
   "livemode"=>false,
   "shop"=>nil,
   "currency"=>"jpy",
   "description"=>nil,
   "amount"=>400,
   "amount_refunded"=>0,
   "customer"=>nil,
   "created"=>1385340172,
   "paid"=>true,
   "refunded"=>false,
   "failure_message"=>nil,
   "card"=>
    #<WebPay::Card:0x007f96cc149ca8
     @attributes=
      {"object"=>"card",
       "exp_year"=>2014,
       "exp_month"=>11,
       "fingerprint"=>"215b5b2fe460809b8bb90bae6eeac0e0e0987bd7",
       "name"=>"KEI KUBO",
       "country"=>"JP",
       "type"=>"Visa",
       "cvc_check"=>"pass",
       "last4"=>"4242"}>,
   "captured"=>true,
   "expire_time"=>nil}>
WebPay>
```

`charge 3`で先ほどのリストの4つ目のWebPay::Chargeのオブジェクトが返されました。
ではwebpay-rubyのインタフェースを用いてこれを返金してみます。

```ruby
WebPay> _.refund
=> #<WebPay::Charge:0x007f96cc149c58
 @attributes=
  {"id"=>"ch_9Ka0Q5gDQg8o4sU",
   "object"=>"charge",
   "livemode"=>false,
   "shop"=>nil,
   "currency"=>"jpy",
   "description"=>nil,
   "amount"=>400,
   "amount_refunded"=>400,
   "customer"=>nil,
   "created"=>1385340172,
   "paid"=>true,
   "refunded"=>true,
   "failure_message"=>nil,
   "card"=>
    #<WebPay::Card:0x007f96cc952ee0
     @attributes=
      {"object"=>"card",
       "exp_year"=>2014,
       "exp_month"=>11,
       "fingerprint"=>"215b5b2fe460809b8bb90bae6eeac0e0e0987bd7",
       "name"=>"KEI KUBO",
       "country"=>"JP",
       "type"=>"Visa",
       "cvc_check"=>"pass",
       "last4"=>"4242"}>,
   "captured"=>true,
   "expire_time"=>nil}>
```

返金できました。IRBやPryでは`_`で最後に評価した結果のオブジェクトをそのまま利用出来ます。

対話的なインタフェースがアシストしてくれるおかげで、何となくの作業はぼーっと口を空けていても出来そうな感じがします。（特にidを毎度コピペしたりGUIから操作するのが辛いので、そこを軽減出来るのは効果的です）

まともな形にしてGemにするか、webpay-rubyにbin/webpay-cliとでもして追加するかしたいところです。
それ以前のそもそもで、もっと使いやすいGUIやAPI向けのインタフェースも考えていきたいものです。

## 参考
- [対話型のコンソールアプリをpryの上に構築したらだいぶ楽できた - ただのにっき(2013-11-28)](http://sho.tdiary.net/20131128.html)
- [Custom commands · pry/pry Wiki](https://github.com/pry/pry/wiki/Custom-commands)