しふみんのブログ

しふみんのブログです。

列車運行情報を取得するgemを作った

関東エリアの列車の運行情報を取得するgemを作りました。
標題は目的語が大きく、情報を取得できるのは関東エリアのみです(大事なことなので)

github.com traininfo_kanto | RubyGems.org | your community gem host

インストール

Gemfileに下記の行を追加して bundle install するか、

# Gemfile
gem 'traininfo_kanto'

あるいは、直接gemをインストールしてください。

gem install traininfo_kanto

使い方

# app.rb
require 'traininfo_kanto'

TraininfoKanto.get(['山手線', '京浜東北線'], url: true)

こんなコードを用意しておいて

$ ruby app.rb

実行すると

["山手線は平常運転です。", "京浜東北線は列車遅延があります。\n宇都宮線内でドア点検を行った影響で、一部列車に遅れが出ています。 (9月21日 16時45分掲載)\nhttps://transit.yahoo.co.jp/traininfo/detail/22/0/"]

が返ってきます。

url オプションがあり、 true にすると「平常運転」以外の場合に最後に詳細ページのリンクを追加します(デフォルトは false )

コマンド

CLIも用意しているので、コマンドライン上で

$ traininfo_kanto get 山手線 京浜東北線
山手線は平常運転です。
京浜東北線は列車遅延があります。
宇都宮線内でドア点検を行った影響で、一部列車に遅れが出ています。 (9月21日 16時45分掲載)

みたいな感じでも使えます。 CLIでは url オプションはなしです(そのうち実装するかも)

Docker

shifumin/traininfo_kanto - Docker Hub

Docker Hubにイメージを上げたので、Dockerの実行環境があれば

$ docker run --rm shifumin/traininfo_kanto get 山手線 京浜東北線

で試すことができます。
Rubyの環境すら必要ありません。
便利ですね。

どうやって情報を取得しているか

単純にYahoo!路線情報の運行ページ{:target='_blank'}をnokogiriでスクレイピングして情報を取得しています。

やりたかったこと

要はこういうことをやりたかったんですよね。

f:id:shifumin:20181010200426p:plain

上記はうちのSlack botです。
で、運行情報取得部分だけgemに切り出しました。

注意点

さて、注意点があります。
関東の運行情報と言いながら現時点(2018年10月9日)でサポートしている路線は下記だけです。
(メトロ、都営とJRの僕が利用しそうな路線と後小湊鉄道だけ)
JRは頑張って後で追加します。私鉄は……w

Supported routes

まだできていないこと

  • サポートしている路線の数が少ない
    • せめてJR東日本(関東)の路線は全てカバーしたい
  • テストを全く書いていない
    • gemのテストの知見を得たいので書きたい
  • CLItraininfo_kanto list (運行情報を取得できる路線一覧を取得する)のサブコマンドくらいは流石に実装したい
    • 実装します

終わりに

Rubygems作成とDockerHubにDocker imageアップロードは初めてでしたが、学びがありよかったです。
こちらからは以上です。

第2回 DockerとCircleCIを使ってRailsアプリの自動テスト&自動Herokuへのデプロイ環境を作っていく

前回の記事の続きです。

前回の記事

shifumin.hatenablog.com

前回は作成したテンプレートの紹介でした。 今回は前回の記事で作成したテンプレートを使って実際にRailsアプリ開発環境を作っていきます。
タイトルは紛らわしいのであとで変更するかもしれません。

使用するテンプレートは下記のリポジトリです。

github.com

動かし方

最低限のそれはGitHubのREADMEに書いていますので、そちらも見てください。
https://github.com/shifumin/docker_rails_heroku

必要な環境

  • Gitのインストール, GitHubのアカウント, Herokuのアカウント作成辺りは前提として
  • Docker
    • Macなら "Docker for Mac"をインストールが楽
      • 詳しくは下記を参照のこと

www.docker.com

  • Heroku CLI
    • Ma(ry Homebrewで brew install heroku が楽

構成

2018年7月7日現在は下記の構成のRailsアプリとなっています。

準備

docker(docker-compose)コマンドの実行はDockerを起動させておく必要があるので起動させてから実行していきます。

まず、必要なDocker imageをpullします。

docker pull ruby:2.5.1
docker pull postgres:10.4

次にリポジトリをcloneします。

git clone git@github.com:shifumin/docker_rails_heroku
cd docker_rails_heroku

rails newしてアプリを作成していきます。

docker-compose run --rm web rails new . --database=postgresql --skip-bundle --skip-test

Overwrite /rails_app/README.md? (enter "h" for help) [Ynaqdh] Y
Overwrite /rails_app/.gitignore? (enter "h" for help) [Ynaqdh] n
Overwrite /rails_app/Gemfile? (enter "h" for help) [Ynaqdh] Y

README.mdは上書きしてもしなくても、.gitignoreは上書きせずにGemfileは上書きします(Y n Y)

database.yml.sampleをコピーしてconfig/database.ymlを置き換えます。
Gemfileにお好みで追加のgemを加えます。

cp -i database.yml.sample config/database.yml
overwrite config/database.yml? (y/n [n]) y

vim Gemfile

僕は今RailsでLine botを作成しているので下記を追加しました。

# adding
group :development, :test do
  gem 'factory_bot_rails'
  gem 'rspec-rails'
end

group :development do
  gem 'awesome_print'
  gem 'pry-byebug'
  gem 'pry-doc'
  gem 'pry-rails'
  gem 'pry-stack_explorer'
  gem 'refe2'
  gem 'tapp'
end

Gemfileにgemを追加したら、bundle installします。
tzinfo-data はウィンドーズ以外は必要なさそうなので削除しました(下記の2行)

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

参考

github.com

余談ですが、僕の場合はbot開発なのでview関係のgem(sass-rails等)は必要ないけど、そのまま残しているのでそれらもきちんと整理する必要がありますね。

ここらでdocker-compose buildします(buildの時に合わせてbundle installもするし、上のbundle installはいらない気がしてきた!)

docker-compose build

一応、RSpecのインストールも済ませておきます(面倒がらずに個人開発でもテストもきちんと書いていくぞというやっていく気持ちの現れ)
また、rails db:createも行います。

docker-compose run --rm web rails g rspec:install
docker-compose run --rm web rails db:create

ここまでの前準備でローカル開発環境ではRailsアプリを動かす準備ができたのでdocker-compose upで起動させてブラウザで確認します。

docker-compose up

http://localhost:3000/ で確認。

f:id:shifumin:20180708113319p:plain

確認できました。

終わりに

今回はDockerized Railsアプリのテンプレートでローカル開発環境でRailsアプリを起動させるところまで進めました。
次回はCircleCIの設定を進めていきたいと思います(予定)

参考

shifumin/docker_rails_heroku: Template for building Rails application environment with Docker on Heroku.
https://github.com/shifumin/docker_rails_heroku

Docker For Mac | Docker
https://www.docker.com/docker-mac

library/ruby - Docker Hub
https://hub.docker.com/_/ruby/

library/postgres - Docker Hub
https://hub.docker.com/_/postgres/

"The dependency tzinfo-data will be unused" on Ubuntu · Issue #12 · tzinfo/tzinfo-data
https://github.com/tzinfo/tzinfo-data/issues/12

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

Gitでローカルのブランチをコピーする方法

先日、GitでローカルのブランチAをコピーして同内容のブランチBを作る方法がないじゃん!とあれこれ悩んだので、このことをすっかり忘れて今後悩む時が来た時のために忘備録を残しておきます。

TL;DR

コピーしたいブランチから git checkout -b でブランチを作成する。

以下全てが余談

なぜ、いつもやっていることなのに変に難しく考えてしまってこんな簡単なことに気づかなかったんだという気持ちしかないですね。よく考えなくても、ブランチを作成した直後って派生元のブランチと全く同じ状態だから、言うなればそれがコピーじゃん!

当初は変に難しく「 -m でブランチの名前を変更することはできるけど、ブランチをコピーする方法はないな。リモートリポジトリを経由するしか方法はないか……」と考えてしまって

  1. ローカルのブランチAをリモートにpushする
    git push origin branchA
  2. ローカルのブランチAの名前を変更する
    git branch -m branchA branchB
  3. リモートのブランチAをローカルでcheckoutする
    git checkout branchA

上記の手順でブランチAをコピーしてブランチBを作るしかないかと思っていたけど、全然そんなことはなかった!ただ単にブランチAから git checkout -b するだけでよかった!

結局、Twitterでボソッと呟いた時にフォロワーからもらった助言で気づけたので、やはり悩みは外に出してみた方がいいなと思いました。

Heroku+RailsでLine botを作る 第10回 ローカル開発環境での動作確認

前回までのあらすじ

第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回: shifumin.hatenablog.com

公式サンプルコードのオウム返しbotRailsへ実装(移植)しました。
またそのRailsアプリをHerokuへとデプロイし動作することを確認しました(第一部完)
今回はローカル開発環境での動作確認をやっていきたいと思います。

ngrok

ローカル開発環境での動作確認はngrokというツールを使います。
このツールを使うとローカル開発環境で動かしているサーバに対してパブリックなURLを割り当てることができます。
詳しくは下記をご参照ください。

ngrok.com qiita.com

LINE bot開発だと、そのURLをbotのチャンネル設定の「Webhook URL」に設定することによっていちいちHerokuにデプロイしなくても修正したコードの動作確認を行えるようになります。
便利ですね。

Homebrew-Cask

ngrokは公式の通りにインストールしてもいいのですが、面倒なのでHomebrew-Caskを使ってインストールしましょう。
Homebrew-Caskについては詳しくは下記をご参照ください(投げ)
簡単にいうと、macOSアプリケーションについてのHomebrewです。

参考: Homebrew-Cask

Homebrew-Caskを利用するためにHomebrewでtapします。

brew tap caskroom/cask

これでHomebrew-Caskを利用できるようになったのでngrokをインストールします。

brew cask install ngrok

direnv

前回の記事でRailsアプリを動かすために LINE_CHANNEL_SECRETLINE_CHANNEL_TOKEN環境変数をHerokuにセットしました。
同様に、ローカル開発環境でも動かすために同じ環境変数をセットする必要があります。

ローカル開発環境の環境変数のセットには direnv を使いましょう。
direnvについては詳しくは下記をご参照ください。

github.com qiita.com

Rails 環境変数」の文脈だとdotenvが有名な気がしますが、僕はdirenvの方が好きなのでこの連載ではdirenvを使います。
direnvの方が好きな理由は、下記のリンク先の記事にもありますが、dotenvだとアプリ内に明示的にdotenvのロードを記述する必要があるからです。
direnvはそれをする必要がありません(最初にシェルに設定を書く必要がありますが)

参考: DotenvではなくDirenvを使う | SOTA

それではHomebrewでdirenvをインストールしましょう。

brew install direnv

次にシェルに設定を記述します。
下記はシェルがbashの場合です。
他のシェルをお使いの方はよしなにやってください。

echo 'eval "$(direnv hook bash)"' >> ~/.bash_profile

初期設定が完了したので環境変数を設定していきます。
公式的には direnv edit ですが、各種エディタでプロジェクトディレクトリのルートに .envrc を作成すれば大丈夫なはずです。

direnv edit . # path/to/your-project/.envrc をエディタで作成/編集する

必要な環境変数LINE_CHANNEL_SECRETLINE_CHANNEL_TOKEN の2つなので、 .envrc には下記の2行を書きます。

export LINE_CHANNEL_SECRET=<your_line_channel_secret>
export LINE_CHANNEL_TOKEN=<your_channel_token>

あとはdirenvが自動で環境変数を設定してくれるはずですが、読み込まれていなかったりエラーが発生した場合は direnv allow すればいいようです。

dieenv allow

試しにそれぞれの環境変数が設定されていることを確認してみましょう。

echo $LINE_CHANNEL_SECRET
<設定したLINE_CHANNEL_SECRETが出力される>
echo $LINE_CHANNEL_TOKEN
<設定したLINE_CHANNEL_TOKENが出力される>

ちゃんと環境変数が設定されているようです。

ローカル開発環境での動作確認

ここまででローカル開発環境で動作確認を行う準備が整いました。
なので、実際に動作確認を行なっていきましょう。
PostgreSQLサーバは起動しているものとします。
起動していない場合は下記のコマンドでPostgreSQLサーバを起動させます。

brew services start postgresql # 停止コマンドは brew services stop postgresql

続いて、Railsサーバを起動させます。

bin/rails s # あるいは bundle exec rails s

Railsサーバを起動させた状態でターミナルの別ウィンドウを開くなどして別のコマンドライン上でngrokを起動させます。

ngrok http 3000 # 停止は Ctrl + C

表示が切り替わり、例えば下記のような出力となるはずです。

ngrok by @inconshreveable

Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.2.8
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://cb413e80.ngrok.io -> localhost:3000
Forwarding                    https://cb413e80.ngrok.io -> localhost:3000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

重要なのは、 Forwarding の2つ目の値で、これが意味するところは、
「ローカルでRailsサーバが動いている localhost:3000https://cb413e80.ngrok.io というパブリックなURLにポートフォワーディングしている」

となります。
パブリックURLなので、自分のMac以外からも、つまりLINE Messaging APIからも自分のMacで動いているRailsサーバにアクセスさせることができます。
というわけで、このURLをLINE botの「Webhook URL」に設定しましょう。

f:id:shifumin:20180501213845p:plain

これで、 rails s を起動しているかつ ngrok http 3000 を起動している状態だとローカル開発環境から直でLINE botの動作を確認することができます。
例えば、コードを修正してbotの動作を変更させた時に、いちいちHerokuにデプロイすることなく動作を確認することができます。
楽でいいですね。
ちなみ、ngrokの起動を止めるとパブリックURLへのフォワーディングも止まります。
また、割り当てられるパブリックURLも起動のたびに異なるものとなります(= ngrokの起動のたびにWebhook URLの設定の変更は必要)

終わりに

今回はローカル環境での動作確認をやっていきました。
次回は今回の続きでローカル環境でのデバッグをやっていきましょう。

参考

ngrok - secure introspectable tunnels to localhost
https://ngrok.com/

ngrokを使用してローカル環境を外部に公開する - Qiita
https://qiita.com/kitaro729/items/44214f9f81d3ebda58bd

Homebrew-Cask
https://caskroom.github.io/

direnv/direnv: Unclutter your .profile
https://github.com/direnv/direnv

direnvを使おう - Qiita
https://qiita.com/kompiro/items/5fc46089247a56243a62

DotenvではなくDirenvを使う | SOTA
https://deeeet.com/writing/2014/05/06/direnv/

Heroku+RailsでLine botを作る 第9回 Herokuへのデプロイ

前回までのあらすじ

第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回: shifumin.hatenablog.com

LINEデベロッパー登録を終え、必要なAPIキーである「Channel Secret」と「アクセストークン」を手に入れました。
また、Railsアプリを作成し、動作することを確認しました。
そして、Railsアプリに公式サンプルコードのオウム返しbotを移植しました。
今回は作成したbotをHerokuにデプロイしていきたいと思います。

git commit

前回でオウム返しbotの実装(移植)が完了しましたので、ここらで git commit をしておきましょう。

git add .
git commit -m "implement echo bot"
git log --stat

commit 8fa85e05cdc2617e31e07b3260ca06417ca9862e (HEAD -> master)
Author: shifumin <hogehogehogehoge@mail.com>
Date:   Sun Apr 29 21:58:24 2018 +0900

    implement echo bot

 app/controllers/webhook_controller.rb | 40 ++++++++++++++++++++++++++++++++++++++++
 config/routes.rb                      |  2 +-
 2 files changed, 41 insertions(+), 1 deletion(-)

前回の変更内容ですね。
ちなみに、GitHubリポジトリを作成し、ここまでのコードを上げておきました(随時更新予定)

github.com

Herokuへのデプロイ

それではHerokuへのデプロイを進めていきましょう。
なお、Herokuのアカウントを作成していることは前提とします。

今回のHerokuアプリケーションの作成は全体的に下記の公式ドキュメント2つを参考にしました。

Herokuでサンプルボットを作成する
Getting Started with Rails 5.x on Heroku | Heroku Dev Center

Heroku CLIのインストール

最初に、コマンドライン上でHerokuを操作するためにHeroku CLIをインストールしましょう。
例のごとくHomebrewを使ってインストールします。

# brew install heroku/brew/heroku でも可
brew install heroku

参考:
devcenter.heroku.com

Herokuアプリの作成

Heroku CLIをインストールできたら、コマンドライン上でHerokuアプリの作成を進めていきます。
まずはHerokuにログインします。

heroku login
(登録したEmailとPasswordの入力)

次にアプリを作成します。
heroku create でherokuが名前を勝手につけてアプリを作成してくれますが、今回は heroku create <app_name> でアプリ名を付けて作成しましょう。

heroku create <your-app-name>
Creating ⬢ <your-app-name>... done
https://<your-app-name>.herokuapp.com/ | https://git.heroku.com/<your-app-name>.git

Herokuの各種設定

アプリのデータベースにPostgreSQLを利用しているので、それ用のHerokuのアドオンを追加します。

heroku addons:create heroku-postgresql:hobby-dev

参考:
devcenter.heroku.com

また、LINE Messaging APIの利用には下記の環境変数が必要なので登録します。
値は、この連載の第1回で確認した Channel Secretアクセストーク となります。

heroku config:set LINE_CHANNEL_SECRET=<your_line_channel_secret>
heroku config:set LINE_CHANNEL_TOKEN=<your_channel_token>

参考:
devcenter.heroku.com

Herokuへのpush

アプリの作成と各種設定が完了したので、ようやくHerokuへpushします。

git push heroku master

しばらく時間がかかります。
Herokuへのpushが完了したら、Herokuアプリの情報を確認してみましょう。
確認は heroku info で行います。

heroku info
=== amurosan-bot
Addons:         heroku-postgresql:hobby-dev
Auto Cert Mgmt: false
Dynos:          web: 1
Git URL:        https://git.heroku.com/<your-app-name>.git
Owner:          your-mail-address@mail.com
Region:         us
Repo Size:      36 KB
Slug Size:      47 MB
Stack:          heroku-16
Web URL:        https://<your-app-name>.herokuapp.com/

一番下の Web URLbotが動作しているURLとなります。
こちらのURLをLINE DevelopersのChannel設定で登録しましょう。
例えば以下のような設定となります。

f:id:shifumin:20180430175408p:plain

LINE botの完成

これでようやく連載第9回にして、オウム返しを行うだけの簡単なLINE botですが、動くものを作成することができました。
めでたいですね。

諸事情によりQRコードを消しました><(ツイートからも読み取れないことを確認済)

動作は前回の記事で貼りましたが、現在は本当にオウム返ししか行いません(行えません)。

f:id:shifumin:20180428230824p:plain

俺たちの戦いはこれからだ!
しふみん先生の次回作にご期待ください。
次回以降でこのbotの機能改善をしていこうと思います。

終わりに

今回は作成したLINE botをHerokuへとデプロイしました。
次回はローカル環境での動作確認とデバッグについて行なっていきましょう。

参考

shifumin/sample-bot-for-line-bot-api: Sample bot using Line :: Bot :: API implemented in Rails on Heroku.
https://github.com/shifumin/sample-bot-for-line-bot-api

Herokuでサンプルボットを作成する - LINE Developers
https://developers.line.me/ja/docs/messaging-api/building-sample-bot-with-heroku/

Getting Started with Rails 5.x on Heroku | Heroku Dev Center
https://devcenter.heroku.com/articles/getting-started-with-rails5

Heroku CLI | Heroku Dev Center
https://devcenter.heroku.com/articles/heroku-cli

Heroku Postgres | Heroku Dev Center
https://devcenter.heroku.com/articles/heroku-postgresql

Configuration and Config Vars | Heroku Dev Center
https://devcenter.heroku.com/articles/config-vars

Heroku+RailsでLine botを作る 第8回 LINE botの雛形の作成

前回までのあらすじ

第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回: shifumin.hatenablog.com

LINEデベロッパー登録を終え、必要なAPIキーである「Channel Secret」と「アクセストークン」を手に入れました。
また、Railsアプリを作成し、動作することを確認しました。
そして、記念すべき(?)はじめてのgit commitを行いました。
今回はLINE botの雛形を作成していきたいと思います。

line-bot-sdk-ruby

github.com

上記がLINE bot開発に使うRuby用のLINE Messaging APISDK(Software Development Kit)となります。

このリポジトリのREADMEのSynopsisにサンプルコードが載せられています。
Railsと同じくRubyのWAF(Web Application Framework)であるSinatraのコードです。
オウム返しを行う実装となっているようですね。

GitHub - line/line-bot-sdk-ruby: Line: :API - SDK of the LINE Messaging API for Ruby.

このサンプルコードをRailsで動くように移植します。
Railsへの移植では下記も大いに参考させていただきました。

qiita.com

Railsへの移植

追加修正・新規作成したファイルは下記の2つです。

  • config/routes.rb (変更)
  • app/controllers/webhook_controller.rb (新規作成)

概要としては、LINE Messaging APIから受け取ったリクエストについてのルーティングを設定して(config/routes.rb)、その際に行うアクションを追加しています(app/controllers/webhook_controller.rb)。

Railsへ移植したコードと一言解説を下記に載せます。

config/routes.rb

Rails.application.routes.draw do
  post '/callback' => 'webhook#callback'
end

<HerokuアプリのURL>/callback にPOSTメソッドのリクエストを受け取った場合にWebbookコントローラのcallbackアクションに割り当てるようにしています。

app/controllers/webhook_controller.rb

require 'line/bot'

class WebhookController < ApplicationController
  protect_from_forgery except: :callback

  def callback
    body = request.body.read

    signature = request.env['HTTP_X_LINE_SIGNATURE']
    unless client.validate_signature(body, signature)
      error 400 do 'Bad Request' end
    end

    events = client.parse_events_from(body)
    events.each { |event|
      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)
        end
      end
    }

    head :ok
  end

  private

  def client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
    }
  end
end

APIトークンを使って認証するため、下記のコードでCSRF対策を無効にしています。
callbackメソッドを除く -> callbackメソッドでは無効。
というか、無効にしないとローカル開発環境で動作確認する時にエラーが出る気がします。

  protect_from_forgery except: :callback

参考:
qiita.com

それ以外はほぼコピペですね。
一応clientメソッドをprivateメソッドに移した以外は。

  def client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
    }
  end

このclientメソッドの中で「Channel Secret」と「アクセストークン」を設定しています(ようやく第1回の伏線(?)を回収できました)
ですので、Herokuで動かす場合はHerokuに、ローカルで動かす場合はローカルに下記の環境変数を設定する必要があります。

  • LINE_CHANNEL_SECRET
  • LINE_CHANNEL_TOKEN

環境変数の設定は必要になった際にやっていきましょう。

終わりに

今回はLINE botの雛形として公式サンプルコードのオウム返しbotRailsへと移植しました。
動き的には下記画像のようにオウム返しを行うbotとなっています。

f:id:shifumin:20180428230824p:plain

次回は作成したこのbotをHerokuにデプロイしていきましょう。

参考

line/line-bot-sdk-ruby: Line: :API - SDK of the LINE Messaging API for Ruby.
https://github.com/line/line-bot-sdk-ruby

今更ながらRails5+line-bot-sdk-ruby+HerokuでLineBot作成してみたら、色々詰まったのでまとめました。 - Qiita
https://qiita.com/y428_b/items/d2b1a376f5900aea30dc

Rails4のCSRF対策で「Can't verify CSRF token authenticity」エラー - Qiita
https://qiita.com/chobi9999/items/2b59fdaf3dd8f2ed9268