はじめに
RailsでRake taskを作成したい。Twitchの関連アプリを作成していて、TwitchのスクリーンネームからユーザーIDなどの情報を取得するコマンドを定義したい。
環境
- ruby 2.5
- rails 5.2
rake task と rails runner
railsでバッチ処理を実装するにあたり、rake taskとrails runnerの2種類が出てきます。下記Qiita記事では rake taskとrails runnerの違いを考察しています。
まあこれ読んでも正直「わからん」という感じなんですが、個人的には下記のような使い分けかなと思っています。
rails db:migrate
やrails assets:precompile
のように、アプリの開発やデプロイに必要なスクリプトは rake task- APIから値を取ってきてDBにinsertするなど、定期処理やアプリケーション動作中に実行する処理は rails runner
今回は「TwitchのユーザーIDを取ってくる」という処理で、そのユーザーIDはconfigやenvなどに設定することを考えているので、「アプリの開発やデプロイに必要なスクリプト」だと考えて、rake taskで実装することを試みます。ただし、rake taskとrails runnerで微妙にお作法などが異なるので、rake taskで実装するのが面倒だと感じたらrails runnerに切り替えていきます。特に、access key などから tokenを取得してくる処理はアプリケーションですでに実装済みなので、そこを使い回せることが条件です。
rake task の作成
./bin/rails --tasks
とするとタスク一覧が出てきます。
$ ./bin/rails --tasks rails about ... rails db:create ...
rails twitch:user
コマンドを作成しようと思います。 rails g task
コマンドを利用します。namespaceがtwitch
なので、 rails g task twitch
とします。
$ rails g task twitch Running via Spring preloader in process 76080 create lib/tasks/twitch.rake
lib/tasks/twitch.rake
というファイルができます。
namespace :twitch do end
タスクを書く
とりあえずhello world
タスクの内容を書いていきます。 rails twitch:user
というタスクを作ろうと思うので、
namespace :twitch do task :user => :environment do puts "task!" end end
こんな感じで書いていきます。とりあえず task!
と出力するだけです。
$ rails twitch:token task!
とりあえず動きました。
RailsのConfigを取得してみる
ではタスクの中身を書いていかなければいけないのですが、twitchのAPIを叩くのにclient_idだったりtokenだったりが必要になるので、rake task上からconfigが引けるのかどうかを確認してみます。
namespace :twitch do task :user => :environment do puts TwitchSummary::Application.config.twitch_client_id end end
TwitchSummary
はアプリケーション名です。
$ rails twitch:user 5exxxxxxxxxxxxxxxxxxxxxxxxxx
秘匿文字列なのでマスクしていますが、Configを取ってくることはできました。
login name から user id が取ってこれるように
では、twitchのライブラリを利用してユーザーIDが取ってこれるようにしてみます。
namespace :twitch do task :user => :environment do twitch_login_name = 'riotgamesjp' @twitch = TwitchRepository.new( TwitchSummary::Application.config.twitch_client_id, TwitchSummary::Application.config.twitch_client_secret, TwitchSummary::Application.config.twitch_redirect_uri ) twitch_token = TwitchSummary::Application.config.twitch_token_utakata user_id = @twitch.get_user_id_by_login(twitch_token, twitch_login_name) puts user_id end end
結果
$ rails twitch:user 104833324
引数を受け取る
んで最後に、twitch_login_name = 'riotgamesjp'
この部分を引数で受け取るようにしてみます。
namespace :twitch do task :user, ['login_name'] => :environment do |task, args| puts 'get user id with "' + args[:login_name] + '"' @twitch = TwitchRepository.new( TwitchSummary::Application.config.twitch_client_id, TwitchSummary::Application.config.twitch_client_secret, TwitchSummary::Application.config.twitch_redirect_uri ) twitch_token = TwitchSummary::Application.config.twitch_token_utakata user_id = @twitch.get_user_id_by_login(twitch_token, args[:login_name]) puts user_id end end
この実行コマンドは以下です。
$ rails twitch:user[riotgamesjp] zsh: no matches found: twitch:user[riotgamesjp]
?!
めっちゃハマりました。zshを使っていると [ が特殊な文字列として表されるっぽいので、こうしたら正しく動きました。
$ rails "twitch:user[riotgamesjp]" get user id with "riotgamesjp" 104833324
正しく取ってこれました
まとめ
- rake taskを書いた
- configとかライブラリとかも全部使える