Herokuデプロイ後にdb:migrateが失敗した時の状況とやったこと
Rails勉強中です。Heroku使用経験もほとんどありません。
トラブル時に途中で混乱して手順を忘れてしまっている部分が多いのですが、
よい勉強になりましたので作業のメモを残しておきます。
全体のまとめ
Herokuにデプロイする前に
Gemfile.lockの中身を消してから
$ bundle install
↓
変更をcommit
↓
$ git push heroku master
↓
$ heroku run rake db:migrate
すればよかったです。
Gemfile.lockを消してbundle install する箇所はbundle updateを実行することでもよいと思います。
前提
Rails5.0.1使用
作業時に使用していたOSはMac OS/X 10.11.6
状況
最新のソースをcommit → $ git push heroku master でデプロイ後、
データベースをmigrateするため、次のコマンドを叩いたらエラーが発生しました。
$ heroku run rake db:migrate
エラーメッセージは次のとおりです。今思えば全て取っておけば良かったのですが、最初の一部だけです。
Running rake db:migrate on ⬢ myapp... up, run.9784 (Free) rake aborted! Gem::LoadError: Specified 'postgresql' for database adapter, but the gem is not loaded. Add `gem 'pg'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord).
対策
公式サイトの導入ガイド
「Getting Started with Rails 5.x on Heroku」 に従ってちゃんと設定を出来ているか(特にdb関連)確認してみました。
Gemfileの確認
公式で「gem 'sqlite3' To this: gem 'pg'」とあるようにHerokuではPostgreSQLがSaas形態で提供されているため、gemはpgを使用する必要があります。
ここで私はproduction環境向けに「gem 'pg'」を指定するのを忘れていましたので、指定しました。
Gemfile
group :production do gem 'pg', '0.15.1' gem 'rails_12factor' end
database.ymlの確認
公式で、databaseのadapterはpostgresql を使うように等々ありましたので見直しました。
データベース名やらユーザー名やらは
$ heroku config
でも確認出来るのですが、Web上で見た方がわかりやすいと思います。
Herokuにログイン→アプリを選択→Add-onsにあるHerokuPostgresをクリック→Database CredentialsのView Credentialsボタンをクリックで参照出来ます。
config/database.yml
# SQLite version 3.x # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' # default: &default adapter: postgresql encoding: utf8 # For details on connection pooling, see rails configuration guide # http://guides.rubyonrails.org/configuring.html#database-pooling pool: 5 # SQLite version 3.x # gem install sqlite3 development: adapter: sqlite3 database: db/development.sqlite3 pool: 5 timeout: 5000 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: adapter: sqlite3 database: db/test.sqlite3 pool: 5 timeout: 5000 # production: <<: *default database: d8c7clp3dmvv4u username: ENV['DATABASE_USER'] password: ENV['DATABASE_PASSWORD'] host: ec2-23-23-222-147.compute-1.amazonaws.com port: 5432
変更をcommitして再度デプロイしましたがエラーが発生しました。
エラーメッセージは次のとおりです。
Running rake db:migrate on ⬢ myapp... up, run.9233 (Free) rake aborted! Gem::LoadError: Specified 'postgresql' for database adapter, but the gem is not loaded. Add `gem 'pg'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord). /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/connection_specification.rb:176:in `rescue in spec' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/connection_specification.rb:173:in `spec' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:53:in `establish_connection' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railtie.rb:125:in `block (2 levels) in <class:Railtie>' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:38:in `instance_eval' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:38:in `execute_hook' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:28:in `block in on_load' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:27:in `each' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:27:in `on_load' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railtie.rb:121:in `block in <class:Railtie>' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:30:in `instance_exec' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:30:in `run' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:55:in `block in run_initializers' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:54:in `run_initializers' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:352:in `initialize!' /app/config/environment.rb:5:in `<top (required)>' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `block in require' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:259:in `load_dependency' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:328:in `require_environment!' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:448:in `block in run_tasks_blocks' /app/vendor/bundle/ruby/2.2.0/gems/rake-12.0.0/exe/rake:27:in `<top (required)>' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:74:in `load' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:74:in `kernel_load' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:27:in `run' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:332:in `exec' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:20:in `dispatch' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:11:in `start' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/exe/bundle:34:in `block in <top (required)>' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/friendly_errors.rb:100:in `with_friendly_errors' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/exe/bundle:26:in `<top (required)>' /app/bin/bundle:3:in `load' /app/bin/bundle:3:in `<main>' Gem::LoadError: can't activate pg (~> 0.18), already activated pg-0.15.1. Make sure all dependencies are added to Gemfile. /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/rubygems_integration.rb:346:in `block (2 levels) in replace_gem' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:2:in `<top (required)>' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `block in require' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:259:in `load_dependency' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/connection_specification.rb:174:in `spec' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:53:in `establish_connection' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railtie.rb:125:in `block (2 levels) in <class:Railtie>' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:38:in `instance_eval' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:38:in `execute_hook' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:28:in `block in on_load' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:27:in `each' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:27:in `on_load' /app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railtie.rb:121:in `block in <class:Railtie>' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:30:in `instance_exec' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:30:in `run' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:55:in `block in run_initializers' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:54:in `run_initializers' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:352:in `initialize!' /app/config/environment.rb:5:in `<top (required)>' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `block in require' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:259:in `load_dependency' /app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:328:in `require_environment!' /app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:448:in `block in run_tasks_blocks' /app/vendor/bundle/ruby/2.2.0/gems/rake-12.0.0/exe/rake:27:in `<top (required)>' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:74:in `load' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:74:in `kernel_load' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:27:in `run' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:332:in `exec' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:20:in `dispatch' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:11:in `start' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/exe/bundle:34:in `block in <top (required)>' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/friendly_errors.rb:100:in `with_friendly_errors' /app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/exe/bundle:26:in `<top (required)>' /app/bin/bundle:3:in `load' /app/bin/bundle:3:in `<main>' Tasks: TOP => db:migrate => environment (See full trace by running task with --trace)
ここで色々調べまくってherokuのプロジェクトを一度消してからやり直したり、
Managing Gems with Bundler | Heroku Dev Centerにあるように開発環境のgemをインストールしないようにしたり、
dotenvを使って環境変数からユーザー名とパスワードを指定しているところを直接書いたりしてみましたが状況が変わることはありませんでした。
エラーメッセージの中に
「Gem::LoadError: can't activate pg (~> 0.18), already activated pg-0.15.1. Make sure all dependencies are added to Gemfile.」
とあるので関係があるかもしれないと思い
gem 'pg', '0.15.1'
としていたところを
gem 'pg'
に変更して、production内に書いているだけではダメかもしれないと、デフォルトのところにも指定してみましたが状況は変わりませんでした。
そこで何となくGemfile.lockをのぞくと
pg (0.15.1)
となっていました。pgのバージョンを指定するのをやめたのに昔のものが残っているのか?と思い内容を全部消去してから
$ bundle install
してから変更をcommitし、あらためてHerokuにデプロイし
$ heroku run rake db:migrate
しますと出来ました!
Running rake db:migrate on ⬢ myapp... up, run.5276 (Free) (54.7ms) CREATE TABLE "schema_migrations" ("version" character varying PRIMARY KEY) (10.7ms) CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) (1.7ms) SELECT pg_try_advisory_lock(4611527472350007090); ActiveRecord::SchemaMigration Load (1.3ms) SELECT "schema_migrations".* FROM "schema_migrations" Migrating to CreateTypes (20170228141646) (1.1ms) BEGIN == 20170228141646 CreateTypes: migrating ====================================== -- create_table(:types) (中略)
試してませんが、Gemfile.lockを消してbundle install する箇所はbundle updateを実行することでもよいと思います。
まとめ
- pg (0.15.1)のままであったとしても何故エラーになるのかがはっきりとはわかりませんでしたが、現時点(2017/03/28)でサーバー側のPostgresSQLは0.19.0が最新のようなので明らかに古いので問題があっとということだと解釈しました。
- 違う環境にデプロイする時はGemfile.lockに注意する必要があることを学習しました。
- 今回の件には関係ありませんが、push時にHeroku側で毎回bundle installしているみたいなのですが、これは省略出来ないのだろうか、できたらいいのにと感じました。やり方はあるのかもしれないのですが、発見できませんでした。
DropboxのPublicフォルダをjsonファイル置き場にしてたが2017年3月15日で廃止したので代替としてFC2ホームページを使うことにした
DropboxのPublicフォルダにはWebホスティング機能があり、そこにファイルを置いて置くだけで世界に公開できるという便利なものだったのですが、
無料ユーザーはとうとう廃止になってしまいました。
私はjsonファイルを置いて検証用のサーバーみたいな使い方をしていたんですが、今回の変更でこの使い方は出来なくなってしまいました。
代替としてブログでおなじみのFC2のサービスの中から「ホームページ」のサービス(「ブログ」ではありませんよ)を使ってjson置き場にすることにしました。
jsonファイルをアップロードして開くとブラウザのURLのBOXのところにURLが表示されるのでそれを使います。
1Gフリースペースがあるので私みたいな使い方なら余裕です。
Material Design Lite for SassでRailsアプリケーションにGoogleのMaterial Design LiteとMaterial IconsとRobotoフォントを導入する
Google製のマテリアルデザインとマテリアルアイコンとRobotoフォントをRubyアプリケーションで使うための「Material Design Lite for Sass」というgemを使います。
このgemはgoogle製Material Design LiteのSaasバージョンです。
導入
Gemfileに次のように記述します。
gem 'material_design_lite-sass'
bundle install しておきます。
/app/assets/stylesheets/application.scss に次のように記述します。
@import 'material';
Attention! デフォルトでは.cssの拡張子でファイルが作成されます。.scssに変更し、*= require_tree . と *= require_selfを削除する必要があります。
オリジナルのapplication.cssをそのままにしたい場合、同じフォルダにcustom.scssを作成し@import 'material'する方法もあります。
app/assets/javascripts/application.js に次のように記述します。
//= require material
TurbolinksについてはMaterial Design Liteはサポートしてないので、READMEを見て下さい。
Material Iconの使い方
<i class="material-icons">info</i>
上の例では"info"のところにマテリアルアイコンの名前を入れます。
マテリアルアイコンの名前は↓のリストにあるものです。
material.io
Saasバージョンで使える変数はこちら↓
material_design_lite-sass/_variables.scss at master · rubysamurai/material_design_lite-sass · GitHub
変数の内容をoverrideする場合は、@importする前に記述する必要があります。↓が例です。
$layout-header-bg-color: rgb(128,128,128) !default; @import 'material';