紙一重の積み重ね

アラフォーのエンジニアがなれる最高の自分を目指して、学んだことをこつこつ情報発信するブログです。

【7章】Ruby on Railsチュートリアル演習まとめ&解答例【7.5プロのデプロイ】

はじめに

Ruby on Rails チュートリアル実例を使ってRailsを学ぼう 第4版の 7章 7.5プロのデプロイの演習まとめ&解答例です。

個人の解答例なので、誤りがあればご指摘ください。

7.5.1 本番環境でのSSL

本章での学び

SSLの有効化

production.rbの# config.force_ssl = trueとなっているコメントアウトを外せばOK。

config.force_ssl = true

SSL証明書

チュートリアルでは、Herokuの証明書に便乗する。 Herokuのサブドメインでのみ有効。

7.5.2 本番環境用のWebサーバー

本章での学び

pumaとは?

チュートリアルの説明では、

Pumaは多数のリクエストを捌くことに適したWebサーバです。

とあるため、ApacheやNginxと同じくWEBサーバの一種なのかと思いましたが、 Railsアプリケーションが動くアプリケーションサーバのようです。

Rails開発におけるwebサーバーとアプリケーションサーバーの違い(翻訳)がわかりやすかったです。

Javaで言うところのTomcatがPumaという理解でよさそうです。 (そういえばどっちもネコ科の動物ですね)

pumaの設定

Herokuにpumaをインストールするために、puma.rbを修正する。

各設定ファイルの意味は、Deploying Rails Applications with the Puma Web Server を参照する。

workersの設定を行う。

デフォルトではコメントアウトされている。

# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }

チュートリアルのとおり修正。

# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
スレッドの設定を行う。

デフォルトの書き方はこちら。

# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum, this matches the default thread size of Active Record.
#
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count

threads_countの記載をチュートリアルに習って修正。

# threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count
アプリケーションのプリロード

workerプロセスの起動時間が短縮できるとのこと。 デフォルトではコメントアウトされている。

# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory. If you use this option
# you need to make sure to reconnect any threads in the `on_worker_boot`
# block.
#
# preload_app!

コメントアウトを外す。

preload_app!
Rackup

PumaにRackアプリの起動方法を伝える設定。 Heroku曰く、この記述は、新しいPumaでは必要ないかもしれないとのこと。

Rackとは何なのかわかりにくい。 以下、Qiitaより引用。

Rackとは何か

RackはRubyでWebサーバーを立ち上げるためのインターフェースである。

puma.rbに以下の記述を追加する。

rackup DefaultRackup
ポート番号の設定

pumaがバインドするポート番号の設定。 デフォルトは3000番とのこと。

# Specifies the `port` that Puma will listen on to receive requests, default is 3000.
#
port        ENV.fetch("PORT") { 3000 }

チュートリアルの記述方法に修正する。

#port        ENV.fetch("PORT") { 3000 }
port        ENV['PORT'] || 3000
pumaの環境設定

RACK_ENVで環境を設定する。 [‘RACK_ENV’]はデフォルトで ‘production'に設定されるとのこと。 puma.rbデフォルトの記述は以下の通り。

# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }

チュートリアルの記述方法に修正する。

#environment ENV.fetch("RAILS_ENV") { "development" }
environment ENV['RACK_ENV'] || 'development'
On worker boot

複数のプロセス間で接続を共有できないため、異なるサービスに接続する場合に便利とのこと。 マルチプロセスモードを使用している時にのみ必要な設定。

デフォルトではコメントアウトされている。

# The code in the `on_worker_boot` will be called if you are using
# clustered mode by specifying a number of `workers`. After each worker
# process is booted this block will be run, if you are using `preload_app!`
# option you will want to use this block to reconnect to any threads
# or connections that may have been created at application boot, Ruby
# cannot share connections between processes.
#
# on_worker_boot do

コメントアウトを外して、チュートリアルの記述に修正する。

on_worker_boot do
#   ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
  ActiveRecord::Base.establish_connection
end
Procfileの作成

Heroku上でPumaのプロセスを走らせる設定ファイル。 ルートディレクトリ(Gemfileと同じディレクトリ)に配置すること。

Procfileを生成する。

yokoyan:~/workspace/sample_app (master) $ touch ./Procfile

チュートリアルの記述方法に修正する。

web: bundle exec puma -C config/puma.rb

7.5.3 本番環境へのデプロイ

本章での学び

Herokuへプッシュ

git push herokuを実行する。

yokoyan:~/workspace/sample_app (master) $ git push heroku
Counting objects: 33, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (32/32), done.
Writing objects: 100% (33/33), 5.36 KiB | 0 bytes/s, done.
Total 33 (delta 17), reused 0 (delta 0)
remote: Compressing source files... done.
・・・略・・・
remote: 
remote: Verifying deploy.... done.
To https://git.heroku.com/enigmatic-everglades-70434.git
   358e923..caa663b  master -> master

Herokuのデータベースを更新

heroku run rails db:migrateを実行する。 usersテーブルが生成されていることを確認。

yokoyan:~/workspace/sample_app (master) $ heroku run rails db:migrate
Running rails db:migrate on ⬢ enigmatic-everglades-70434... up, run.5560 (Free)
D, [2017-05-04T00:47:36.558093 #4] DEBUG -- :    (50.1ms)  CREATE TABLE "schema_migrations" ("version" character varying PRIMARY KEY)
D, [2017-05-04T00:47:36.572385 #4] DEBUG -- :    (10.6ms)  CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
D, [2017-05-04T00:47:36.574079 #4] DEBUG -- :    (0.7ms)  SELECT pg_try_advisory_lock(414146247089748600);
D, [2017-05-04T00:47:36.582273 #4] DEBUG -- :   ActiveRecord::SchemaMigration Load (0.8ms)  SELECT "schema_migrations".* FROM "schema_migrations"
I, [2017-05-04T00:47:36.607769 #4]  INFO -- : Migrating to CreateUsers (20170417215343)
D, [2017-05-04T00:47:36.609657 #4] DEBUG -- :    (0.6ms)  BEGIN
== 20170417215343 CreateUsers: migrating ======================================
-- create_table(:users)
D, [2017-05-04T00:47:36.619860 #4] DEBUG -- :    (9.1ms)  CREATE TABLE "users" ("id" serial primary key, "name" character varying, "email" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
   -> 0.0101s
== 20170417215343 CreateUsers: migrated (0.0102s) =============================

D, [2017-05-04T00:47:36.625502 #4] DEBUG -- :   SQL (0.8ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20170417215343"]]
D, [2017-05-04T00:47:36.630375 #4] DEBUG -- :    (4.7ms)  COMMIT
I, [2017-05-04T00:47:36.630459 #4]  INFO -- : Migrating to AddIndexToUsersEmail (20170423125906)
D, [2017-05-04T00:47:36.631619 #4] DEBUG -- :    (0.6ms)  BEGIN
== 20170423125906 AddIndexToUsersEmail: migrating =============================
-- add_index(:users, :email, {:unique=>true})
D, [2017-05-04T00:47:36.637228 #4] DEBUG -- :    (2.9ms)  CREATE UNIQUE INDEX  "index_users_on_email" ON "users"  ("email")
   -> 0.0055s
== 20170423125906 AddIndexToUsersEmail: migrated (0.0056s) ====================

D, [2017-05-04T00:47:36.638677 #4] DEBUG -- :   SQL (0.7ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20170423125906"]]
D, [2017-05-04T00:47:36.640254 #4] DEBUG -- :    (1.4ms)  COMMIT
I, [2017-05-04T00:47:36.640331 #4]  INFO -- : Migrating to AddPasswordDigestToUsers (20170424041610)
D, [2017-05-04T00:47:36.641305 #4] DEBUG -- :    (0.6ms)  BEGIN
== 20170424041610 AddPasswordDigestToUsers: migrating =========================
-- add_column(:users, :password_digest, :string)
D, [2017-05-04T00:47:36.642587 #4] DEBUG -- :    (0.9ms)  ALTER TABLE "users" ADD "password_digest" character varying
   -> 0.0012s
== 20170424041610 AddPasswordDigestToUsers: migrated (0.0013s) ================

D, [2017-05-04T00:47:36.643998 #4] DEBUG -- :   SQL (0.7ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20170424041610"]]
D, [2017-05-04T00:47:36.645525 #4] DEBUG -- :    (1.3ms)  COMMIT
D, [2017-05-04T00:47:36.650975 #4] DEBUG -- :   ActiveRecord::InternalMetadata Load (0.8ms)  SELECT  "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2  [["key", :environment], ["LIMIT", 1]]
D, [2017-05-04T00:47:36.655662 #4] DEBUG -- :    (0.6ms)  BEGIN
D, [2017-05-04T00:47:36.657575 #4] DEBUG -- :   SQL (0.8ms)  INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key"  [["key", "environment"], ["value", "production"], ["created_at", 2017-05-04 00:47:36 UTC], ["updated_at", 2017-05-04 00:47:36 UTC]]
D, [2017-05-04T00:47:36.662078 #4] DEBUG -- :    (4.3ms)  COMMIT
D, [2017-05-04T00:47:36.662950 #4] DEBUG -- :    (0.7ms)  SELECT pg_advisory_unlock(414146247089748600)
yokoyan:~/workspace/sample_app (master) $ 

動作確認

本番環境へアクセス。 あれ・・・?アプリケーションエラー・・・?

image

HerokuでApplicationErrorが発生したときの対処法に従って、Herokuを再起動してみる。

heroku restart --app sample_app

実行結果。sample_appがないとのこと。 デプロイした結果、pumaが起動していないのでは・・・?

yokoyan:~/workspace/sample_app (master) $ heroku restart --app sample_app
Restarting dynos on ⬢ sample_app... !
 ▸    Couldn't find that app.

そもそも開発環境は起動するのか

herokuではなく、cloud9環境で確認。 やっぱりpumaが起動しない。 rackup DefaultRackupNameErrorと言われているのが原因っぽい。

yokoyan:~/workspace/sample_app (master) $ rails server -b $IP -p $PORT
=> Booting Puma
=> Rails 5.0.0.1 application starting in development on http://0.0.0.0:8080
=> Run `rails server -h` for more startup options
Exiting
config/puma.rb:42:in `_load_from': undefined local variable or method `rackup DefaultRackup' for #<Puma::DSL:0x00000003d56df0> (NameError)

やっぱり、自分で調べたとおり、この記述は必要ないのではないか・・・。

Heroku曰く、この記述は、新しいPumaでは必要ないかもしれないとのこと。

一旦コメントアウトして再起動を試みる。

#rackup DefaultRackup

動いた−!

yokoyan:~/workspace/sample_app (master) $ rails server -b $IP -p $PORT
=> Booting Puma
=> Rails 5.0.0.1 application starting in development on http://0.0.0.0:8080
=> Run `rails server -h` for more startup options
[4489] Puma starting in cluster mode...
[4489] * Version 3.4.0 (ruby 2.3.0-p0), codename: Owl Bowl Brawl
[4489] * Min threads: 5, max threads: 5
[4489] * Environment: development
[4489] * Process workers: 2
[4489] * Preloading application
[4489] * Listening on tcp://0.0.0.0:8080
[4489] Use Ctrl-C to stop
[4489] - Worker 0 (pid: 4499) booted, phase: 0
[4489] - Worker 1 (pid: 4503) booted, phase: 0

再度本番環境へデプロイ

ファイルを修正してコミット。gitヘプッシュする。

yokoyan:~/workspace/sample_app (master) $ git add -A
yokoyan:~/workspace/sample_app (master) $ git commit -m "fix puma.rb"
yokoyan:~/workspace/sample_app (master) $ git push                                                                                                           

再度、herokuへデプロイ。

yokoyan:~/workspace/sample_app (master) $ git push heroku

本番環境のURLにアクセスする。 無事に画面が表示されることを確認。 やったー!

image

また、URLがhttpsになっていることを確認。 chromeのF12開発ツールで、証明書が*.herokuapp.comになっていることを確認。

herokuへのデプロイ時のWARNINGについて

以下のエラーが気になっていたが、チュートリアルでは現時点では無視して良いとのこと。 商用でHerokuを使ったアプリケーションを動かす場合は、GemfileでRubyのバージョンを明示しておいた方が賢明。

remote: ###### WARNING:
remote:        You have not declared a Ruby version in your Gemfile.
remote:        To set your Ruby version add this line to your Gemfile:
remote:        ruby '2.2.6'
remote:        # See https://devcenter.heroku.com/articles/ruby-versions for more information.

演習1

ブラウザから本番環境 (Heroku) にアクセスし、SSLの鍵マークがかかっているか、URLがhttpsになっているかどうかを確認してみましょう。

確認済み。

演習2

本番環境でユーザーを作成してみましょう。Gravatarの画像は正しく表示されているでしょうか?

本番環境のデータベースを一度リセットする。

yokoyan:~/workspace/sample_app (master) $ rails db:migrate:reset

登録前のユーザ数を確認。 0であることを確認。

yokoyan:~/workspace/sample_app (master) $ rails console
Running via Spring preloader in process 5718
Loading development environment (Rails 5.0.0.1)
>> User.count
   (0.2ms)  SELECT COUNT(*) FROM "users"
=> 0

本番環境で自分のGravatar画像が表示されることを確認。

image

登録後のユーザ数を確認。

>> User.count
   (0.4ms)  SELECT COUNT(*) FROM "users"
=> 0

あれ?増えてない。 原因は、rails consoleで、developmentの環境を読み込んでいるためか。

本番環境でrails consoleを起動する

rails consoleの引数に、-e productionまたは、--environment=productionをつける。

yokoyan:~/workspace/sample_app (master) $ rails console -e production
Running via Spring preloader in process 5757
Loading production environment (Rails 5.0.0.1)

本番環境のユーザ数を確認。エラー。

>> User.count
ActiveRecord::StatementInvalid: Could not find table 'users'

あれ? 本番環境のデータベースファイル/sample_app/db/production.sqlite3をダウンロード。 ・・・できない。 cloud9で中身を開くと、なんと中身が空だった。

本番環境のデータベースを作成する

チュートリアル内のコマンド$ rails db:migrate RAILS_ENV=productionで、本番環境のデータベースを作成する。

yokoyan:~/workspace/sample_app (master) $ rails db:migrate RAILS_ENV=production
== 20170417215343 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0021s
== 20170417215343 CreateUsers: migrated (0.0022s) =============================

== 20170423125906 AddIndexToUsersEmail: migrating =============================
-- add_index(:users, :email, {:unique=>true})
   -> 0.0025s
== 20170423125906 AddIndexToUsersEmail: migrated (0.0027s) ====================

== 20170424041610 AddPasswordDigestToUsers: migrating =========================
-- add_column(:users, :password_digest, :string)
   -> 0.0023s
== 20170424041610 AddPasswordDigestToUsers: migrated (0.0024s) ================

念の為、再度heroku run rails db:migrateを行う。

yokoyan:~/workspace/sample_app (master) $ heroku run rails db:migrate
Running rails db:migrate on ⬢ enigmatic-everglades-70434... up, run.1365 (Free)
D, [2017-05-04T02:45:02.150105 #4] DEBUG -- :    (1.2ms)  SELECT pg_try_advisory_lock(414146247089748600);
D, [2017-05-04T02:45:02.159794 #4] DEBUG -- :   ActiveRecord::SchemaMigration Load (2.0ms)  SELECT "schema_migrations".* FROM "schema_migrations"
D, [2017-05-04T02:45:02.182959 #4] DEBUG -- :   ActiveRecord::InternalMetadata Load (1.3ms)  SELECT  "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2  [["key", :environment], ["LIMIT", 1]]
D, [2017-05-04T02:45:02.190909 #4] DEBUG -- :    (3.1ms)  BEGIN
D, [2017-05-04T02:45:02.193480 #4] DEBUG -- :    (1.0ms)  COMMIT
D, [2017-05-04T02:45:02.194797 #4] DEBUG -- :    (1.1ms)  SELECT pg_advisory_unlock(414146247089748600)

再度、本番環境の動作確認

本番環境のユーザ数を確認する。 本番環境のユーザが0であることを確認。

yokoyan:~/workspace/sample_app (master) $ rails console -e production
Running via Spring preloader in process 6340
Loading production environment (Rails 5.0.0.1)
>> User.count
   (3.2ms)  SELECT COUNT(*) FROM "users"
=> 0

再度、本番環境の画面からユーザ登録を行う。 メールアドレスがすでに登録されているとエラーが出る。 んんんん???? 本番環境なのに、developmentのデータベースを参照しているような動きをしている。

image

heroku内のデータベースの状態を確認

heroku pg:psqlで接続できる。

yokoyan:~/workspace/sample_app (master) $ heroku pg:psql
--> Connecting to postgresql-infinite-44520
psql (9.3.15, server 9.6.1)
WARNING: psql major version 9.3, server major version 9.6.
         Some psql features might not work.
SSL connection (cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.

SQLを実行してみる。確かに、すでにユーザがいる。

enigmatic-everglades-70434::DATABASE=> select * from users;
 id |  name   |        email         |         created_at         |         updated_at         |                       password_digest                        
----+---------+----------------------+----------------------------+----------------------------+--------------------------------------------------------------
  1 | yokoyan | yokoyan@example.com | 2017-05-04 02:12:23.993016 | 2017-05-04 02:12:23.993016 | $2a$10$VyFTuDbiD09sd91PCtRHiuEbHXR3Bn/odBYrMo6E1hCcIf7MCTIB.
(1 row)

終了するときは、バックスラッシュ(または\マーク)+qを使う。

enigmatic-everglades-70434::DATABASE=> \q

本番環境のデータベースを初期化

heroku run rails db:migrate:resetを実行する。

実行すると、ActiveRecord::ProtectedEnvironmentErrorが発生。 エラーログより、回避するためには、DISABLE_DATABASE_ENVIRONMENT_CHECK=1が必要とのこと。

yokoyan:~/workspace/sample_app (master) $ heroku run rails db:migrate:reset
Running rails db:migrate:reset on ⬢ enigmatic-everglades-70434... up, run.7726 (Free)
D, [2017-05-05T22:28:54.173744 #4] DEBUG -- :   ActiveRecord::SchemaMigration Load (0.9ms)  SELECT "schema_migrations".* FROM "schema_migrations"
D, [2017-05-05T22:28:54.194566 #4] DEBUG -- :    (1.0ms)  SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1  [["key", :environment]]
D, [2017-05-05T22:28:54.196984 #4] DEBUG -- :   ActiveRecord::SchemaMigration Load (0.8ms)  SELECT "schema_migrations".* FROM "schema_migrations"
D, [2017-05-05T22:28:54.200260 #4] DEBUG -- :    (1.4ms)  SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1  [["key", :environment]]
D, [2017-05-05T22:28:54.205980 #4] DEBUG -- :   ActiveRecord::SchemaMigration Load (0.8ms)  SELECT "schema_migrations".* FROM "schema_migrations"
D, [2017-05-05T22:28:54.208606 #4] DEBUG -- :    (0.9ms)  SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1  [["key", :environment]]
rails aborted!
ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database.
If you are sure you want to continue, run the same command with the environment variable:
DISABLE_DATABASE_ENVIRONMENT_CHECK=1
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/database_tasks.rb:51:in `check_protected_environments!'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railties/databases.rake:11:in `block (2 levels) in <top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/commands/rake_proxy.rb:13:in `block in run_rake_task'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/commands/rake_proxy.rb:10:in `run_rake_task'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/commands/commands_tasks.rb:51:in `run_command!'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/commands.rb:18:in `<top (required)>'
/app/bin/rails:9:in `require'
/app/bin/rails:9:in `<main>'
Tasks: TOP => db:migrate:reset => db:drop => db:check_protected_environments
(See full trace by running task with --trace) 

オプションを付与して、heroku run rails db:migrate:reset DISABLE_DATABASE_ENVIRONMENT_CHECK=1を実行。

またしてもエラー。 今度は権限がないとのこと。

yokoyan:~/workspace/sample_app (master) $ heroku run rails db:migrate:reset DISABLE_DATABASE_ENVIRONMENT_CHECK=1
Running rails db:migrate:reset DISABLE_DATABASE_ENVIRONMENT_CHECK=1 on ⬢ enigmatic-everglades-70434... up, run.7676 (Free)
FATAL:  permission denied for database "postgres"
DETAIL:  User does not have CONNECT privilege.
Couldn't drop database 'dba0ongobagkn'
rails aborted!
PG::ConnectionBad: FATAL:  permission denied for database "postgres"
DETAIL:  User does not have CONNECT privilege.
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:671:in `initialize'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:671:in `new'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:671:in `connect'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:217:in `initialize'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:37:in `new'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:37:in `postgresql_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:721:in `new_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:765:in `checkout_new_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:744:in `try_to_checkout_new_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:705:in `acquire_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:501:in `checkout'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:364:in `connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:875:in `retrieve_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:128:in `retrieve_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:91:in `connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/postgresql_database_tasks.rb:6:in `connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/postgresql_database_tasks.rb:28:in `drop'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/database_tasks.rb:136:in `drop'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/database_tasks.rb:152:in `block in drop_current'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/database_tasks.rb:292:in `block in each_current_configuration'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/database_tasks.rb:291:in `each'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/database_tasks.rb:291:in `each_current_configuration'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/tasks/database_tasks.rb:151:in `drop_current'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railties/databases.rake:42:in `block (2 levels) in <top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railties/databases.rake:38:in `block (2 levels) in <top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/commands/rake_proxy.rb:13:in `block in run_rake_task'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/commands/rake_proxy.rb:10:in `run_rake_task'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/commands/commands_tasks.rb:51:in `run_command!'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/commands.rb:18:in `<top (required)>'
/app/bin/rails:9:in `require'
/app/bin/rails:9:in `<main>'
Tasks: TOP => db:drop:_unsafe
(See full trace by running task with --trace)

heroku上のデータベースをリセットする

調べた結果、heroku上のデータベースをリセットするには、やり方が異なるようだ。 heroku上のDBをリセットする

上記の記事のやり方に習って、heroku pg:reset DATABASE_URLを実行する。

yokoyan:~/workspace/sample_app (master) $ heroku pg:reset DATABASE_URL
 ▸    WARNING: Destructive action
 ▸    postgresql-infinite-44520 will lose all of its data
 ▸    
 ▸    To proceed, type enigmatic-everglades-70434 or re-run this command with --confirm enigmatic-everglades-70434

> enigmatic-everglades-70434
Resetting postgresql-infinite-44520... done

herokuのデータベースを再構築

heroku run rails db:migrateで再構築する。

yokoyan:~/workspace/sample_app (master) $ heroku run rails db:migrate
Running rails db:migrate on ⬢ enigmatic-everglades-70434... up, run.1527 (Free)
D, [2017-05-06T00:30:06.106972 #4] DEBUG -- :    (17.4ms)  CREATE TABLE "schema_migrations" ("version" character varying PRIMARY KEY)
D, [2017-05-06T00:30:06.136916 #4] DEBUG -- :    (19.5ms)  CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
D, [2017-05-06T00:30:06.152610 #4] DEBUG -- :    (2.6ms)  SELECT pg_try_advisory_lock(414146247089748600);
D, [2017-05-06T00:30:06.249049 #4] DEBUG -- :   ActiveRecord::SchemaMigration Load (24.0ms)  SELECT "schema_migrations".* FROM "schema_migrations"
I, [2017-05-06T00:30:06.278501 #4]  INFO -- : Migrating to CreateUsers (20170417215343)
D, [2017-05-06T00:30:06.308528 #4] DEBUG -- :    (4.9ms)  BEGIN
== 20170417215343 CreateUsers: migrating ======================================
-- create_table(:users)
D, [2017-05-06T00:30:06.356036 #4] DEBUG -- :    (26.9ms)  CREATE TABLE "users" ("id" serial primary key, "name" character varying, "email" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
   -> 0.0441s
== 20170417215343 CreateUsers: migrated (0.0447s) =============================

D, [2017-05-06T00:30:06.384870 #4] DEBUG -- :   SQL (6.6ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20170417215343"]]
D, [2017-05-06T00:30:06.392898 #4] DEBUG -- :    (5.6ms)  COMMIT
I, [2017-05-06T00:30:06.393629 #4]  INFO -- : Migrating to AddIndexToUsersEmail (20170423125906)
D, [2017-05-06T00:30:06.399135 #4] DEBUG -- :    (4.8ms)  BEGIN
== 20170423125906 AddIndexToUsersEmail: migrating =============================
-- add_index(:users, :email, {:unique=>true})
D, [2017-05-06T00:30:06.411975 #4] DEBUG -- :    (4.6ms)  CREATE UNIQUE INDEX  "index_users_on_email" ON "users"  ("email")
   -> 0.0127s
== 20170423125906 AddIndexToUsersEmail: migrated (0.0130s) ====================

D, [2017-05-06T00:30:06.419739 #4] DEBUG -- :   SQL (2.7ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20170423125906"]]
D, [2017-05-06T00:30:06.427897 #4] DEBUG -- :    (7.0ms)  COMMIT
I, [2017-05-06T00:30:06.428056 #4]  INFO -- : Migrating to AddPasswordDigestToUsers (20170424041610)
D, [2017-05-06T00:30:06.432913 #4] DEBUG -- :    (4.1ms)  BEGIN
== 20170424041610 AddPasswordDigestToUsers: migrating =========================
-- add_column(:users, :password_digest, :string)
D, [2017-05-06T00:30:06.438083 #4] DEBUG -- :    (3.4ms)  ALTER TABLE "users" ADD "password_digest" character varying
   -> 0.0059s
== 20170424041610 AddPasswordDigestToUsers: migrated (0.0060s) ================

D, [2017-05-06T00:30:06.444792 #4] DEBUG -- :   SQL (3.6ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20170424041610"]]
D, [2017-05-06T00:30:06.451267 #4] DEBUG -- :    (6.1ms)  COMMIT
D, [2017-05-06T00:30:06.466501 #4] DEBUG -- :   ActiveRecord::InternalMetadata Load (1.6ms)  SELECT  "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2  [["key", :environment], ["LIMIT", 1]]
D, [2017-05-06T00:30:06.477179 #4] DEBUG -- :    (1.6ms)  BEGIN
D, [2017-05-06T00:30:06.482628 #4] DEBUG -- :   SQL (2.2ms)  INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key"  [["key", "environment"], ["value", "production"], ["created_at", 2017-05-06 00:30:06 UTC], ["updated_at", 2017-05-06 00:30:06 UTC]]
D, [2017-05-06T00:30:06.488771 #4] DEBUG -- :    (4.5ms)  COMMIT
D, [2017-05-06T00:30:06.490686 #4] DEBUG -- :    (1.5ms)  SELECT pg_advisory_unlock(414146247089748600)

本番環境のデータベースのユーザ数確認

heroku pg:psqlでherokuのデータベースに接続。 SQLでユーザ数を調べる。ユーザ数が0にリセットされていることを確認。

yokoyan:~/workspace/sample_app (master) $ heroku pg:psql
--> Connecting to postgresql-infinite-44520
psql (9.3.15, server 9.6.1)
WARNING: psql major version 9.3, server major version 9.6.
         Some psql features might not work.
SSL connection (cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.

enigmatic-everglades-70434::DATABASE=> select * from users;
 id | name | email | created_at | updated_at | password_digest 
----+------+-------+------------+------------+-----------------
(0 rows)

production環境のrails consoleのユーザ数も0であることを確認。

yokoyan:~/workspace/sample_app (master) $ rails console -e production
Running via Spring preloader in process 5779
Loading production environment (Rails 5.0.0.1)
>> User.count
   (0.2ms)  SELECT COUNT(*) FROM "users"
=> 0

本番環境の画面からユーザ登録

本番環境から再度、ユーザ登録を実施。 今度は登録が完了した!

image

登録結果の確認

再度、herokuのpostgresqlに接続。 ユーザ数が1に上がっていることを確認。

enigmatic-everglades-70434::DATABASE=> select * from users;
 id |  name   |        email         |         created_at         |         updated_at         |                       password_digest                        
----+---------+----------------------+----------------------------+----------------------------+--------------------------------------------------------------
  1 | yokoyan | yokoyansan@example.com | 2017-05-06 00:35:14.008523 | 2017-05-06 00:35:14.008523 | $2a$10$YYA4PtG8aWNTEcr695wEeuWv/M22z.3JkLHBCHqJPavAzFoilci/q
(1 row)

おわりに

herokuと開発環境の差に、かなりはまってしまいましたが、なんとかリカバリできました。 こういう試行錯誤が、チュートリアルの以下のコラムの意図するところなのかもしれません。 「熟練」になるとは 引き続き次の章もがんばります。