紙一重の積み重ね

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

【12章】Ruby on Railsチュートリアル演習まとめ&解答例【12.4 本番環境でのメール送信 (再掲)】

はじめに

Ruby on Rails チュートリアル実例を使ってRailsを学ぼう 第4版の 12章 12.4 本番環境でのメール送信 (再掲)の演習まとめ&回答例です。

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

動作環境

  • cloud9
  • ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
  • Rails 5.0.0.1

12.4 本番環境でのメール送信

本章での学び

SendGridとHerokuを使った環境設定なので省略。 詳細は以下参照。

35歳だけどRailsチュートリアルやってみた。[第4版 11章 11.4 本番環境でのメール送信 まとめ&解答例]

本番環境へのデプロイ

gitへのpush

yokoyan:~/workspace/sample_app (master) $ git push
Warning: Permanently added 'bitbucket.org,104.192.143.2' (RSA) to the list of known hosts.
Counting objects: 38, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (36/36), done.
Writing objects: 100% (38/38), 5.81 KiB | 0 bytes/s, done.
Total 38 (delta 22), reused 0 (delta 0)
To bitbucket.org:yokoyan/sample_app.git
   81be683..583552c  master -> master

本番環境へのデプロイ

yokoyan:~/workspace/sample_app (master) $ git push heroku
Counting objects: 38, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (36/36), done.
Writing objects: 100% (38/38), 5.81 KiB | 0 bytes/s, done.
Total 38 (delta 22), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Ruby app detected
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.2.6
remote: -----> Installing dependencies using bundler 1.15.1
remote:        Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
remote:        Fetching gem metadata from https://rubygems.org/.........
remote:        Fetching version metadata from https://rubygems.org/..
remote:        Fetching dependency metadata from https://rubygems.org/.
remote:        Using rake 12.0.0
remote:        Using concurrent-ruby 1.0.5
remote:        Using i18n 0.8.1
remote:        Using minitest 5.10.1
remote:        Using thread_safe 0.3.6
remote:        Using builder 3.2.3
remote:        Using erubis 2.7.0
remote:        Using mini_portile2 2.1.0
remote:        Using rack 2.0.1
remote:        Using nio4r 1.2.1
remote:        Using websocket-extensions 0.1.2
remote:        Using mime-types-data 3.2016.0521
remote:        Using arel 7.1.4
remote:        Using method_source 0.8.2
remote:        Using thor 0.19.4
remote:        Using bundler 1.15.1
remote:        Using bcrypt 3.1.11
remote:        Using will_paginate 3.1.0
remote:        Using execjs 2.7.0
remote:        Using sass 3.4.23
remote:        Using puma 3.4.0
remote:        Using tilt 2.0.6
remote:        Using coffee-script-source 1.12.2
remote:        Using turbolinks-source 5.0.0
remote:        Using multi_json 1.12.1
remote:        Using pg 0.18.4
remote:        Using faker 1.6.6
remote:        Using tzinfo 1.2.2
remote:        Using nokogiri 1.7.0.1
remote:        Using rack-test 0.6.3
remote:        Using websocket-driver 0.6.5
remote:        Using mime-types 3.1
remote:        Using sprockets 3.7.1
remote:        Using bootstrap-will_paginate 0.0.10
remote:        Using autoprefixer-rails 6.7.7.1
remote:        Using uglifier 3.0.0
remote:        Using turbolinks 5.0.1
remote:        Using coffee-script 2.4.1
remote:        Using activesupport 5.0.0.1
remote:        Using loofah 2.0.3
remote:        Using mail 2.6.4
remote:        Using bootstrap-sass 3.3.6
remote:        Using rails-dom-testing 2.0.2
remote:        Using globalid 0.3.7
remote:        Using activemodel 5.0.0.1
remote:        Using jbuilder 2.4.1
remote:        Using rails-html-sanitizer 1.0.3
remote:        Using activejob 5.0.0.1
remote:        Using activerecord 5.0.0.1
remote:        Using actionview 5.0.0.1
remote:        Using actionpack 5.0.0.1
remote:        Using actioncable 5.0.0.1
remote:        Using actionmailer 5.0.0.1
remote:        Using railties 5.0.0.1
remote:        Using sprockets-rails 3.2.0
remote:        Using sass-rails 5.0.6
remote:        Using coffee-rails 4.2.1
remote:        Using jquery-rails 4.1.1
remote:        Using rails 5.0.0.1
remote:        Bundle complete! 25 Gemfile dependencies, 59 gems now installed.
remote:        Gems in the groups development and test were not installed.
remote:        Bundled gems are installed into ./vendor/bundle.
remote:        The latest bundler is 1.15.2, but you are currently running 1.15.1.
remote:        To update, run `gem install bundler`
remote:        Bundle completed (2.63s)
remote:        Cleaning up the bundler cache.
remote:        The latest bundler is 1.15.2, but you are currently running 1.15.1.
remote:        To update, run `gem install bundler`
remote: -----> Installing node-v6.11.1-linux-x64
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile
remote:        I, [2017-07-17T21:27:17.657710 #426]  INFO -- : Writing /tmp/build_2f8a6517b5621aeee4ac52fb92d612f3/public/assets/application-89e6500f2055e9eab169c030a3561a92813a5ce017b6e67ab0df3311b0430f3a.js
remote:        I, [2017-07-17T21:27:17.658277 #426]  INFO -- : Writing /tmp/build_2f8a6517b5621aeee4ac52fb92d612f3/public/assets/application-89e6500f2055e9eab169c030a3561a92813a5ce017b6e67ab0df3311b0430f3a.js.gz
remote:        Asset precompilation completed (9.36s)
remote:        Cleaning assets
remote:        Running: rake assets:clean
remote:        I, [2017-07-17T21:27:22.642501 #445]  INFO -- : Removed application-df52b44ba712a102868f0a043f9a078ac6718902bb3bbd1343d89fed6d71ea09.js
remote: 
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.
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types     -> web
remote:        Default types for buildpack -> console, rake, worker
remote: 
remote: -----> Compressing...
remote:        Done: 38.3M
remote: -----> Launching...
remote:        Released v17
remote:        https://enigmatic-everglades-70434.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/enigmatic-everglades-70434.git
   81be683..583552c  master -> master

本番DBのマイグレーション

yokoyan:~/workspace/sample_app (master) $ heroku run rails db:migrate
 ▸    heroku-cli: This CLI is deprecated. Please reinstall from https://cli.heroku.com
Running rails db:migrate on ⬢ enigmatic-everglades-70434... up, run.8511 (Free)
D, [2017-07-17T21:28:47.717023 #4] DEBUG -- :    (1.1ms)  SELECT pg_try_advisory_lock(414146247089748600);
D, [2017-07-17T21:28:47.729908 #4] DEBUG -- :   ActiveRecord::SchemaMigration Load (4.8ms)  SELECT "schema_migrations".* FROM "schema_migrations"
I, [2017-07-17T21:28:47.750804 #4]  INFO -- : Migrating to AddResetToUsers (20170703042006)
D, [2017-07-17T21:28:47.755178 #4] DEBUG -- :    (3.2ms)  BEGIN
== 20170703042006 AddResetToUsers: migrating ==================================
-- add_column(:users, :reset_digest, :string)
D, [2017-07-17T21:28:47.762588 #4] DEBUG -- :    (7.0ms)  ALTER TABLE "users" ADD "reset_digest" character varying
   -> 0.0073s
-- add_column(:users, :reset_sent_at, :datetime)
D, [2017-07-17T21:28:47.764156 #4] DEBUG -- :    (1.2ms)  ALTER TABLE "users" ADD "reset_sent_at" timestamp
   -> 0.0015s
== 20170703042006 AddResetToUsers: migrated (0.0089s) =========================

D, [2017-07-17T21:28:47.774368 #4] DEBUG -- :   SQL (6.6ms)  INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "version"  [["version", "20170703042006"]]
D, [2017-07-17T21:28:47.776549 #4] DEBUG -- :    (1.8ms)  COMMIT
D, [2017-07-17T21:28:47.792921 #4] DEBUG -- :   ActiveRecord::InternalMetadata Load (3.7ms)  SELECT  "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2  [["key", :environment], ["LIMIT", 1]]
D, [2017-07-17T21:28:47.798638 #4] DEBUG -- :    (0.9ms)  BEGIN
D, [2017-07-17T21:28:47.802672 #4] DEBUG -- :    (2.9ms)  COMMIT
D, [2017-07-17T21:28:47.804204 #4] DEBUG -- :    (1.3ms)  SELECT pg_advisory_unlock(414146247089748600)

本番環境での動作確認

10分メールでアドレスを取得して会員登録を行う。 その後、パスワード再設定を行う。

image

herokuログ

heroku logs --tailでログを確認。

2017-07-17T21:39:31.530251+00:00 app[web.1]: I, [2017-07-17T21:39:31.530197 #11]  INFO -- : [860a37ff-aacc-4986-9181-c816f0d3a3bd] Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms)
2017-07-17T21:39:31.530718+00:00 app[web.1]: F, [2017-07-17T21:39:31.530667 #11] FATAL -- : [860a37ff-aacc-4986-9181-c816f0d3a3bd]   
2017-07-17T21:39:31.530777+00:00 app[web.1]: F, [2017-07-17T21:39:31.530725 #11] FATAL -- : [860a37ff-aacc-4986-9181-c816f0d3a3bd] NoMethodError (undefined method `[]' for nil:NilClass):
2017-07-17T21:39:31.530824+00:00 app[web.1]: F, [2017-07-17T21:39:31.530777 #11] FATAL -- : [860a37ff-aacc-4986-9181-c816f0d3a3bd]   
2017-07-17T21:39:31.530896+00:00 app[web.1]: F, [2017-07-17T21:39:31.530824 #11] FATAL -- : [860a37ff-aacc-4986-9181-c816f0d3a3bd] app/controllers/password_resets_controller.rb:10:in `create'

演習1

production環境でユーザー登録を試してみましょう。ユーザー登録時に入力したメールアドレスにメールは届きましたか? 10分メールアドレスでアドレスを取得して会員登録を行う。 メールが届いたことを確認。

image.png

演習2

メールを受信できたら、実際にメールをクリックしてアカウントを有効化してみましょう。また、Heroku上のログを調べてみて、有効化に関するログがどうなっているのか調べてみてください。ヒント: ターミナルからheroku logsコマンドを実行してみましょう。

アカウントを有効化できることを確認。

image.png

アカウント有効時のログが出力されていることを確認。

2017-07-19T04:16:04.322404+00:00 app[web.1]: I, [2017-07-19T04:16:04.322291 #7]  INFO -- : [3668efeb-d720-41c2-b708-8249f0213275] Started GET "/account_activations/NK83qY_IcQOSN8pwFmZWHQ/edit?email=lqy57919%40oalsp.com" for 125.199.218.217 at 2017-07-19 04:16:04 +0000
2017-07-19T04:16:04.326858+00:00 app[web.1]: I, [2017-07-19T04:16:04.326749 #7]  INFO -- : [3668efeb-d720-41c2-b708-8249f0213275] Processing by AccountActivationsController#edit as HTML
2017-07-19T04:16:04.326935+00:00 app[web.1]: I, [2017-07-19T04:16:04.326872 #7]  INFO -- : [3668efeb-d720-41c2-b708-8249f0213275]   Parameters: {"email"=>"lqy57919@oalsp.com", "id"=>"NK83qY_IcQOSN8pwFmZWHQ"}
2017-07-19T04:16:04.351571+00:00 app[web.1]: D, [2017-07-19T04:16:04.351460 #7] DEBUG -- : [3668efeb-d720-41c2-b708-8249f0213275]   User Load (1.2ms)  SELECT  "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2  [["email", "lqy57919@oalsp.com"], ["LIMIT", 1]]
2017-07-19T04:16:04.444411+00:00 app[web.1]: D, [2017-07-19T04:16:04.444257 #7] DEBUG -- : [3668efeb-d720-41c2-b708-8249f0213275]   SQL (4.0ms)  UPDATE "users" SET "activated" = 't', "activated_at" = '2017-07-19 04:16:04.438558' WHERE "users"."id" = $1  [["id", 105]]
2017-07-19T04:16:04.447347+00:00 app[web.1]: I, [2017-07-19T04:16:04.447273 #7]  INFO -- : [3668efeb-d720-41c2-b708-8249f0213275] Redirected to http://enigmatic-everglades-70434.herokuapp.com/users/105
2017-07-19T04:16:04.447604+00:00 app[web.1]: I, [2017-07-19T04:16:04.447543 #7]  INFO -- : [3668efeb-d720-41c2-b708-8249f0213275] Completed 302 Found in 121ms (ActiveRecord: 5.9ms)
2017-07-19T04:16:04.448155+00:00 heroku[router]: at=info method=GET path="/account_activations/NK83qY_IcQOSN8pwFmZWHQ/edit?email=lqy57919%40oalsp.com" host=enigmatic-everglades-70434.herokuapp.com request_id=3668efeb-d720-41c2-b708-8249f0213275 fwd="125.199.218.217" dyno=web.1 connect=0ms service=131ms status=302 bytes=975 protocol=http
2017-07-19T04:16:04.862697+00:00 heroku[router]: at=info method=GET path="/users/105" host=enigmatic-everglades-70434.herokuapp.com request_id=3debf180-f75c-4d20-b686-6bd6831ee3b2 fwd="125.199.218.217" dyno=web.1 connect=0ms service=24ms status=200 bytes=2896 protocol=http
2017-07-19T04:16:04.846760+00:00 app[web.1]: I, [2017-07-19T04:16:04.846639 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2] Started GET "/users/105" for 125.199.218.217 at 2017-07-19 04:16:04 +0000
2017-07-19T04:16:04.848792+00:00 app[web.1]: I, [2017-07-19T04:16:04.848712 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2] Processing by UsersController#show as HTML
2017-07-19T04:16:04.848906+00:00 app[web.1]: I, [2017-07-19T04:16:04.848837 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   Parameters: {"id"=>"105"}
2017-07-19T04:16:04.853189+00:00 app[web.1]: D, [2017-07-19T04:16:04.853071 #7] DEBUG -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   User Load (0.9ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 105], ["LIMIT", 1]]
2017-07-19T04:16:04.855994+00:00 app[web.1]: I, [2017-07-19T04:16:04.855886 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   Rendering users/show.html.erb within layouts/application
2017-07-19T04:16:04.857370+00:00 app[web.1]: I, [2017-07-19T04:16:04.857313 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   Rendered users/show.html.erb within layouts/application (1.2ms)
2017-07-19T04:16:04.858613+00:00 app[web.1]: I, [2017-07-19T04:16:04.858558 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   Rendered layouts/_rails_default.html.erb (0.9ms)
2017-07-19T04:16:04.858945+00:00 app[web.1]: I, [2017-07-19T04:16:04.858881 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   Rendered layouts/_shim.html.erb (0.1ms)
2017-07-19T04:16:04.861308+00:00 app[web.1]: D, [2017-07-19T04:16:04.861232 #7] DEBUG -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   User Load (0.8ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 105], ["LIMIT", 1]]
2017-07-19T04:16:04.862347+00:00 app[web.1]: I, [2017-07-19T04:16:04.862272 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   Rendered layouts/_header.html.erb (3.1ms)
2017-07-19T04:16:04.862874+00:00 app[web.1]: I, [2017-07-19T04:16:04.862820 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2]   Rendered layouts/_footer.html.erb (0.2ms)
2017-07-19T04:16:04.863242+00:00 app[web.1]: I, [2017-07-19T04:16:04.863172 #7]  INFO -- : [3debf180-f75c-4d20-b686-6bd6831ee3b2] Completed 200 OK in 14ms (Views: 7.1ms | ActiveRecord: 1.7ms)
2017-07-19T04:16:05.288229+00:00 heroku[router]: at=info method=GET path="/assets/application-89e6500f2055e9eab169c030a3561a92813a5ce017b6e67ab0df3311b0430f3a.js" host=enigmatic-everglades-70434.herokuapp.com request_id=f82893f9-1743-4308-aaf2-4a2fcb2ad63e fwd="125.199.218.217" dyno=web.1 connect=0ms service=2ms status=304 bytes=48 protocol=http
2017-07-19T04:16:07.264932+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=enigmatic-everglades-70434.herokuapp.com request_id=922625db-fd2d-44ef-8f33-0c34d0bb12cb fwd="125.199.218.217" dyno=web.1 connect=0ms service=2ms status=200 bytes=143 protocol=http

演習3

アカウントを有効化できたら、今度はパスワードの再設定を試してみましょう。正しくパスワードの再設定ができたでしょうか?

パスワードの再設定を行う。

image.png

パスワード再設定メールが受信できることを確認。

image.png

パスワードの再設定ができることを確認。

image.png

おわりに

パスワードリマインダーが完成しました。 本章は、全体的にpassword_resetと書くべき所を、password_resetsと書いてしまったり、 またその逆があったり、些細なコーディングミスで詰まったことが多い章でした。皆様もお気をつけ下さい。