しふみんのブログ

しふみんのブログです。

Heroku+RailsでLine botを作る 第11回 ローカル開発環境でのデバッグ

前回までのあらすじ

第1回: http://shifumin.hatenablog.com/entry/2018/04/20/000500
第2回: http://shifumin.hatenablog.com/entry/2018/04/22/002000
第3回: http://shifumin.hatenablog.com/entry/2018/04/23/000500
第4回: http://shifumin.hatenablog.com/entry/2018/04/24/000500
第5回: http://shifumin.hatenablog.com/entry/2018/04/25/000500
第6回: http://shifumin.hatenablog.com/entry/2018/04/26/000500
第7回: http://shifumin.hatenablog.com/entry/2018/04/27/000500
第8回: http://shifumin.hatenablog.com/entry/2018/04/29/000500
第9回: http://shifumin.hatenablog.com/entry/2018/04/30/002000
第10回: shifumin.hatenablog.com

公式サンプルコードのオウム返しbotRailsへ実装(移植)し、Herokuへとデプロイし動作することを確認しました(第一部完)
また、ローカル開発環境での動作確認の方法を調べました。
今回は前回の続きでローカル開発環境でのデバッグの方法を見ていきたいと思います。

Gemの追加

Gemfile

まずデバッグ用のGemを追加しましょう。
追加するのは下記の5つです。
Railsデバッグ用gemは他にもありますがLINE bot開発で使えそうなのはこれらくらいでしょうか。
Gemfileの最後に group :development で追加しましょう。

(前略)
group :development do
  gem 'awesome_print'
  gem 'pry-byebug'
  gem 'pry-rails'
  gem 'pry-stack_explorer'
  gem 'tapp'
end

Gemfileにgemを追加したらそれらのgemをインストールしましょう。

bundle install

gemの詳細はそれぞれのGitHubリポジトリに任せます。

github.com github.com github.com github.com github.com

以下、各Gemの一言解説です。

awesome_print

デバッグ時にオブジェクトのデータ構造を綺麗に表示してくれる。

pry-byebug

プログラムの好きなところでピンポイントで止めてステップ実行でデバッグできる。

pry-rails

Rails Consoleでpryを使えるようにする。

pry-stack_explorer

デバッグ中にコールスタックを移動できる。

tapp

レシーバを pp しながら返す tapp を使うことができる。

僕が大昔に書いたQiitaの記事も合わせてどうぞ(同じことしか書いていませんが)

qiita.com

実際のデバッグ

実際にデバッグを行なっていきましょう。
コードのデバッグしたい位置に binding.pry を埋め込みます。
この binding.pry を埋め込んだ位置がブレークポイントとなり、プログラムが実行された時にその箇所で一旦停止します。

app/controllers/webhook_controller.rb の16行目(下記の3行目)に binding.pry を埋め込みました。
ループの中の event の中身がどうなっているかを確認するためです。

     events = client.parse_events_from(body)
     events.each { |event|
       binding.pry # ここに埋め込んだぞo(^-^)o
       case event
       when Line::Bot::Event::Message
         case event.type
         when Line::Bot::Event::MessageType::Text
           message = {
             type: 'text',
             text: event.message['text']
           }
           client.reply_message(event['replyToken'], message)
         when Line::Bot::Event::MessageType::Image
         end
       end
     }

     head :ok
   end

ブレークポイントを埋め込んで、Railsアプリ(bot)とngrokを起動させて動作確認をできる状態で、botに例えば「テスト」とメッセージを送ってみます。

Frame number: 0/69

From: /path/to/app/controllers/webhook_controller.rb @ line 17 WebhookController#callback:

     6: def callback
     7:   body = request.body.read
     8:
     9:   signature = request.env['HTTP_X_LINE_SIGNATURE']
    10:   unless client.validate_signature(body, signature)
    11:     error 400 do 'Bad Request' end
    12:   end
    13:
    14:   events = client.parse_events_from(body)
    15:   events.each { |event|
    16:     binding.pry
 => 17:     case event
    18:     when Line::Bot::Event::Message
    19:       case event.type
    20:       when Line::Bot::Event::MessageType::Text
    21:         message = {
    22:           type: 'text',
    23:           text: event.message['text']
    24:         }
    25:         client.reply_message(event['replyToken'], message)
    26:       when Line::Bot::Event::MessageType::Image
    27:       end
    28:     end
    29:   }
    30:
    31:   head :ok
    32: end

5.2.0@2.5.1 (#<WebhookController:0x00007f85fbe503e8>)>

概ね、上記のようになると思います。
メッセージを送ったので WebhookController#callback が呼ばれて、16行目に binding.pry を埋め込んだので、直後の17行目でプログラムが一時停止しています。
ここで、変数 event の情報を知りたいので、event を調べてみます。

5.2.0@2.5.1 (#<WebhookController:0x00007f85fbe503e8>)> event
#<Line::Bot::Event::Message:0x00007f85fbdb1e28 @src={"type"=>"message", "replyToken"=>"1bccd66640cf4b8098ca2422785998f5", "source
=>{"userId"=>"Ue9cef635faec1f63eeed49f190d3baad", "type"=>"user"}, "timestamp"=>1530371340095, "message"=>{"type"=>"text", "id"=>
8193953148916", "text"=>"テスト"}}>、

変数 event の情報が分かりました。
また eventtype を調べると下記のようになります。

5.2.0@2.5.1 (#<WebhookController:0x00007f85fbe503e8>)> event.type
"text"

この event はスタンプを送った場合は下記のように

5.2.0@2.5.1 (#<WebhookController:0x00007f85f91169e0>)> event
#<Line::Bot::Event::Message:0x00007f85fbe28820 @src={"type"=>"message", "replyToken"=>"6dddf3aa4cd14fbeadbfcf9b3d0633ca", "source"=>{"userId"=>"Ue9cef635faec1f63eeed49f190d3baad", "type"=>"user"}, "timestamp"=>1530372349972, "message"=>{"type"=>"sticker", "id"=>"8194033895954", "stickerId"=>"2591647", "packageId"=>"1062629"}}>

5.2.0@2.5.1 (#<WebhookController:0x00007f85fbcc80e8>)> event.type
"sticker"

また、画像を送った場合は下記のようになります。

5.2.0@2.5.1 (#<WebhookController:0x00007f85f8eeba08>)> event
#<Line::Bot::Event::Message:0x00007f85fda81ee0 @src={"type"=>"message", "replyToken"=>"6ef3f17524004110a3cf9aada9bcb992", "source"=>{"userId"=>"Ue9cef635faec1f63eeed49f190d3baad", "type"=>"user"}, "timestamp"=>1530372296992, "message"=>{"type"=>"image", "id"=>"8194029881000"}}>

5.2.0@2.5.1 (#<WebhookController:0x00007f85f8eeba08>)> event.type
"image"

下記は、ブレークポイントで停止させた後に実際に変数を調べている様子です。

Image from Gyazo

また、下記はステップ実行で1行ずつプログラムを進めている様子です。

Image from Gyazo

ステップ実行では、下記のコマンド等でプログラムを進めることができます。

next: 次の行に進める
step : メソッドの内部に入る
finish: 現在のメソッドを抜ける
continue: デバッグを終了する(プログラムの実行をconfinueする)
whereami: 表示を現在のスコープのソースコードに戻す

実際は whereaminext を一々タイプするのは面倒なのでもちろんエイリアスを設定しているのですが、きちんと?正式コマンドをタイプしています、これはデモなので。。。
そのうち、pryの設定ファイルである .pryrc の記事を書くかもしれません。

pryを使ったデバッグについて詳しいことは下記の記事をご参照ください(投げ)
他にも色々とコマンドがあります。

qiita.com

qiita.com

終わりに

今回はローカル環境でのデバッグを見ていきました。
次回ではLINE bot開発に戻り、機能追加を進めていきましょう。

参考

awesome-print/awesome_print: Pretty print your Ruby objects with style -- in full color and with proper indentation
https://github.com/awesome-print/awesome_print

deivid-rodriguez/pry-byebug: Step-by-step debugging and stack navigation in Pry
https://github.com/deivid-rodriguez/pry-byebug

rweng/pry-rails: Rails >= 3 pry initializer
https://github.com/rweng/pry-rails

pry/pry-stack_explorer: Walk the stack in a Pry session
https://github.com/pry/pry-stack_explorer

esminc/tapp: tap { pp self }
https://github.com/esminc/tapp

Rubyプロジェクトの始め方の備忘録 - Qiita
https://qiita.com/shifumin/items/e065dd5b35bc22497037

今更聞けないpryの使い方と便利プラグイン集 - Qiita https://qiita.com/k0kubun/items/b118e9ccaef8707c4d9f

pry-byebugでrubyデバッグする - Qiita
https://qiita.com/AknYk416/items/6f0bec58712edaf4940e