はじめに
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は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) $
動作確認
本番環境へアクセス。 あれ・・・?アプリケーションエラー・・・?
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 DefaultRackup
がNameError
と言われているのが原因っぽい。
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にアクセスする。 無事に画面が表示されることを確認。 やったー!
また、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画像が表示されることを確認。
登録後のユーザ数を確認。
>> 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のデータベースを参照しているような動きをしている。
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
本番環境の画面からユーザ登録
本番環境から再度、ユーザ登録を実施。 今度は登録が完了した!
登録結果の確認
再度、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と開発環境の差に、かなりはまってしまいましたが、なんとかリカバリできました。 こういう試行錯誤が、チュートリアルの以下のコラムの意図するところなのかもしれません。 「熟練」になるとは 引き続き次の章もがんばります。