概要
今回、個人開発のアプリをHerokuでデプロイしrakeタスクでYouTube APIを叩こうとした際にエラーが出たので、その原因と解決方法をまとめました。
環境
Ruby : 2.6.6
Rails : 6.0.3
Heroku : 7.59.1
MySQL : 8.0.26
OS : macOS Catalina
発生したエラー
$ heroku run rake youtube_task:youtube_video_save
Running rake youtube_task:youtube_video_save on ⬢ mukinator... up, run.8232 (Free)
rake aborted!
NoMethodError: undefined method `[]' for nil:NilClass
/app/lib/tasks/youtube_task.rake:11:in `block (2 levels) in <main>'
/app/vendor/bundle/ruby/2.6.0/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/cli/exec.rb:63:in `load'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/cli/exec.rb:63:in `kernel_load'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/cli/exec.rb:28:in `run'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/cli.rb:474:in `exec'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/cli.rb:30:in `dispatch'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/cli.rb:24:in `start'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/exe/bundle:49:in `block in <top (required)>'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/lib/bundler/friendly_errors.rb:128:in `with_friendly_errors'
/app/vendor/bundle/ruby/2.6.0/gems/bundler-2.2.21/exe/bundle:37:in `<top (required)>'
/app/bin/bundle:113:in `load'
/app/bin/bundle:113:in `<main>'
Tasks: TOP => youtube_task:youtube_video_save
(See full trace by running task with --trace)
エラーログを見ると
NoMethodError: undefined method `[]' for nil:NilClass
何かがnilになっていることがわかり、その場所が
/app/lib/tasks/youtube_task.rake:11:in `block (2 levels) in <main>'
と書いてあるので該当の箇所を見てみると、
youtube.key = Rails.application.credentials.youtube[:youtube_api_key]
このコードでエラーが起きてたみたいです。
ここのコードではYouTube APIを使うためにAPI keyを渡しているのですがうまく渡せていなかったようです。
原因
今回の自分のアプリではAPI keyを管理する方法としてrailsの機能として備わっている「credentials」を使っています。
今回はcredentialsについての記事ではないため説明は省略します。
詳しくは以下の記事を参考にしてください。
credentialsについて簡単に言うと、公開したくない情報など(今回で言えばYouTube APIのAPI key)を管理するための機能です。
秘密にしておきたい情報を「credentials.yml.enc」に書いて管理するのですが、これにはmaster.keyが必要です。
master.keyがないとcredentials.yml.encの中の読み書きができないわけです。
ですが今回、このmaster.keyをHerokuに設定していませんでした。
そのためcredentials.yml.encの中にあるAPI keyを取得できないため youtube.key が nil となりエラーが起きたと考えています。
.gitignoreにmaster.keyが記述されているのでHerokuには渡らないですよね。
/config/master.key
解決方法
原因はわかりました。
Herokuにmaster.keyを設定してあげれば動きそうなので設定しましょう。
master.keyを環境変数として設定するのですが、やり方として2つあります。
- Herokuのサイトから設定する方法
- ターミナルから設定する方法
どちらか片方で大丈夫なので、お好きな方で設定してください。
Herokuのサイトから設定する方法
1. Herokuのサイトにログインする
サイトにアクセスしてログインしましょう。
2. 対象のアプリを選択
対象のアプリを選択し、上のタブから「settings」を選択する
3. Config Varsの「Reveal Config Vars」をクリック
4. 「KEY」と「VALUE」をそれぞれ設定し保存
今回はmaster.keyを設定するので「KEY」は「MASTER_KEY」のように分かりやすい名前がいいと思います。
「VALUE」はそれぞれの値を入れてください。
これでサイトからmaster.keyを環境変数として設定することができました。
ターミナルから設定する方法
もう一つのやり方、ターミナルを使った設定方法です。
アプリがあるディレクトリに移動します。
今設定されている環境変数を確認します。
以下のコマンドで設定されている環境変数(KEY と VALUE)が表示されます。
$ heroku config
設定のやり方は以下の通りです。
$ heroku config:set 顕教変数名=値
具体的なコマンドは以下のようになると思います。
*「=」の前後にスペースが入ってしまうと設定できないので注意してください。
$ heroku config:set MASTER_KEY=`cat config/master.key`
環境変数として設定したので確認してみましょう。
$ heroku config
上記のコマンドで今設定した環境変数(master.key)が表示されていれば設定の完了です。
再度YouTube APIを叩いてみる
master.keyをHerokuに設定したのでもう一度rakeタスクを実行してYouTube APIを叩いてみましょう。
$ heroku run rake youtube_task:youtube_video_save
再度実行したらちゃんとrakeタスクが実行され動画が取得できました👏
今回のエラーに遭遇して思ったこと
ローカルでは動いているのに、Herokuにデプロイしてcredentials関係でエラーが出たらmaster.keyも視野に入れて考えてみると良いと思います。
最後に
最後まで読んでいただきありがとうございます。
少しでも役に立ったなら幸いです。
おまけ
今回作ったアプリの紹介
「MUKINATOR」(ムキネイター)
日常で生まれる悩みや不安を全て筋トレで解決するアプリです。
使ってもらえると嬉しいです。
Qiita記事