はじめに
最近、プロジェクト管理業務が業務の大半を占めており、
プログラムを書く機会がなかなかありません。
このままだとプログラムがまったく書けない人になってしまう危機感(迫り来る35歳定年説)と、
新しいことに挑戦したいという思いから、
Ruby on Rails チュートリアル実例を使ってRailsを学ぼう 第4版を学習中です。
業務で使うのはもっぱらJavaなのですが、Rails楽しいですね。
これまでEvernoteに記録していましたが、ソースコードの貼付けに限界を感じたため、
Qiitaで自分が学習した結果をアウトプットしていきます。
個人の解答例なので、誤りがあればご指摘ください。
動作環境
- cloud9
- ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
- Rails 5.0.0.1
12.2.1 パスワード再設定のメールとテンプレート
本章での学び
【Mailer】Userメイラーの実装
自動生成されたメール送信処理のメソッドpassword_reset
の中身を実装する。
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.user_mailer.password_reset.subject
#
def password_reset
@greeting = "Hi"
mail to: "to@example.org"
end
上記のコードは削除して、下記の通り編集する。
def password_reset(user)
@user = user
mail to: user.email, subject: "Password reset"
end
【Mailer】メールテンプレートの実装
自動生成されているtextメールのテンプレートの中身を実装する。
To reset your password click the link below:
<%= edit_password_reset_url(@user.reset_token, email: @user.email) %>
This link will expire in tow hours.
If you did not request your password to be reset, please ignore this email and your password will stay as it is.
自動生成されているhtmlメールのテンプレートの中身を実装する。
<h1>Password reset</h1>
<p>To reset your password click the link below:</p>
<%= link_to "Reset password", edit_password_reset_url(@user.reset_token, email: @user.email) %>
<p>This link will expire in two hours.</p>
<p>
If you did not request your password to be reset, please ignore this email and your password will stay as it is.
</p>
【Mailer】プレビュー処理の実装
自動生成されたプレビュー処理の中身を実装する。
# Preview this email at http://localhost:3000/rails/mailers/user_mailer/password_reset
def password_reset
UserMailer.password_reset
end
上記のコードを削除して、下記のとおり実装する。
def password_reset
user = User.first
user.reset_token = User.new_token
UserMailer.password_reset(user)
end
動作確認前の注意点
本項目の実行環境は、developであるため、実際にメールは送信されない。
(production環境でなければ、実際にメールは飛ばない)
私はdevelop環境であることを失念していたので、メールが飛ばないのはなぜかと、小一時間悩みました。。。
プレビュー処理の動作確認
下記のURLにアクセスして動作確認を行う。
https://xxxxxxx/rails/mailers/user_mailer/password_reset
textメールのプレビューができることを確認。
htmlメールのプレビューができることを確認。
パスワード再設定メール送信処理の動作確認
ブラウザを起動し、有効なメールアドレスを入力して、パスワード再設定メールを送信する。
動作確認のためのメールアドレスは、10分メールアドレスを使うと便利。
ブラウザ上で、パスワード再送信メールが送信できたメッセージが表示されたことを確認。
コンソールログの確認
入力したメールアドレス宛に、パスワード再設定メールが送信されていることを確認。
Sent mail to hsa09793@tqosi.com (8.3ms)
Date: Sun, 09 Jul 2017 01:24:46 +0000
From: noreply@example.com
To: hsa09793@tqosi.com
Message-ID: <596185de75f24_dcf20b491898558@yokoyan-rails-tutorial-4550834.mail>
Subject: Password reset
Mime-Version: 1.0
Content-Type: multipart/alternative;
boundary="--==_mimepart_596185de74823_dcf20b491898458";
charset=UTF-8
Content-Transfer-Encoding: 7bit
----==_mimepart_596185de74823_dcf20b491898458
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
To reset your password click the link below:
https://rails-tutorial-yokoyan.c9users.io/password_resets/UDO5Wja1Uh_eiltpVaPxpw/edit?email=hsa09793%40tqosi.com
This link will expire in tow hours.
If you did not request your password to be reset, please ignore this email and your password will stay as it is.
----==_mimepart_596185de74823_dcf20b491898458
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
/* Email styles need to be inline */
</style>
</head>
<body>
<h1>Password reset</h1>
<p>To reset your password click the link below:</p>
<a href="https://rails-tutorial-yokoyan.c9users.io/password_resets/UDO5Wja1Uh_eiltpVaPxpw/edit?email=hsa09793%40tqosi.com">Reset password</a>
<p>This link will expire in two hours.</p>
<p>
If you did not request your password to be reset, please ignore this email and your password will stay as it is.
</p>
</body>
</html>
演習1
ブラウザから、送信メールのプレビューをしてみましょう。「Date」の欄にはどんな情報が表示されているでしょうか?
UTC時間が表示される。
日本時間から9時間ずれて表示される。
演習2
パスワード再設定フォームから有効なメールアドレスを送信してみましょう。また、Railsサーバーのログを見て、生成された送信メールの内容を確認してみてください。
前述の「コンソールログの確認」参照。
演習3
コンソールに移り、先ほどの演習課題でパスワード再設定をしたUserオブジェクトを探してください。オブジェクトを見つけたら、そのオブジェクトが持つreset_digestとreset_sent_atの値を確認してみましょう。
演習2で使用したユーザーのメールアドレスで検索。
reset_digest
と、reset_sent_at
に値が入っていることを確認。
yokoyan:~/workspace/sample_app (password-reset) $ rails console --sandbox
Running via Spring preloader in process 3587
Loading development environment in sandbox (Rails 5.0.0.1)
Any modifications you make will be rolled back on exit
>>
?> user = User.find_by(email: "hsa09793@tqosi.com")
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "hsa09793@tqosi.com"], ["LIMIT", 1]]
=> #<User id: 103, name: "mail_test", email: "hsa09793@tqosi.com", created_at: "2017-07-09 01:06:40", updated_at: "2017-07-09 01:24:46", password_digest: "$2a$10$F42JIypvQYXBt6V2pe7A4ONXQ4PImXqR0GSK7ioCrj5...", remember_digest: nil, admin: false, activation_digest: "$2a$10$V4Z1Rgva0TA.FJqv7/SWAO/vfjX0sBSpgLpKjx8itK7...", activated: nil, activated_at: nil, reset_digest: "$2a$10$dsfjyWCpuX.9I4c7zbWYieBp4nxc.fzipFaYHyaHcP8...", reset_sent_at: "2017-07-09 01:24:46">
>>
?> user.reset_digest
=> "$2a$10$dsfjyWCpuX.9I4c7zbWYieBp4nxc.fzipFaYHyaHcP83yMQRBtFaO"
>>
?> user.reset_sent_at
=> Sun, 09 Jul 2017 01:24:46 UTC +00:00
12.2.2 送信メールのテスト
本章での学び
【test】パスワード再設定用メイラーメソッドのテストを作成
11章でコメントアウトしていたテストコードを実装する。
- michaelユーザの情報を取得
- パスワード再設定トークンを生成
- パスワード再設定メールを送信
- メールオブジェクトの件名に、"Password reset"が含まれているかチェック
- メールオブジェクトの宛先が、ユーザのemailと一致しているかチェック
- メールオブジェクトのfromアドレスが、
noreply@example.com
と一致しているかチェック - テストユーザのパスワード再設定トークンが、エンコードされたメール本文内に存在するかチェック
- テストユーザのアドレスがエスケープされて、エンコードされたメール本文に含まれているかチェックする
上記を踏まえて実装する。
test "password_reset" do
user = users(:michael)
user.reset_token = User.new_token
mail = UserMailer.password_reset(user)
assert_equal "Password reset", mail.subject
assert_equal [user.email], mail.to
assert_equal ["noreply@example.com"], mail.from
assert_match user.reset_token, mail.body.encoded
assert_match CGI.escape(user.email), mail.body.encoded
end
動作確認
テストコードがgreenになることを確認。
yokoyan:~/workspace/sample_app (password-reset) $ rails test
Running via Spring preloader in process 5896
Started with run options --seed 1346
47/47: [===================================================================================================] 100% Time: 00:00:02, Time: 00:00:02
Finished in 2.88912s
47 tests, 205 assertions, 0 failures, 0 errors, 0 skips
演習1
メイラーのテストだけを実行してみてください。このテストは greenになっているでしょうか?
メイラーのテストだけ実行する。
rails test test/ディレクトリ名/ファイル名
greenになることを確認。
yokoyan:~/workspace/sample_app (password-reset) $ rails test test/mailers/user_mailer_test.rb
Running via Spring preloader in process 6095
Started with run options --seed 2562
2/2: [=====================================================================================================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.67604s
2 tests, 16 assertions, 0 failures, 0 errors, 0 skips
演習2
リスト 12.12にある2つ目のCGI.escapeを削除すると、テストが redになることを確認してみましょう。
エスケープ処理をコメントアウトする。
# assert_match CGI.escape(user.email), mail.body.encoded
assert_match user.email, mail.body.encoded
テストがredになることを確認。
yokoyan:~/workspace/sample_app (password-reset) $ rails test test/mailers/user_mailer_test.rb
Running via Spring preloader in process 6187
Started with run options --seed 5175
FAIL["test_password_reset", UserMailerTest, 0.6262194160372019]
test_password_reset#UserMailerTest (0.63s)
Expected /michael@example\.com/ to match # encoding: US-ASCII
"\r\n----==_mimepart_596197d92db13_182bcc70e015864\r\nContent-Type: text/plain;\r\n charset=UTF-8\r\nContent-Transfer-Encoding: 7bit\r\n\r\nTo reset your password click the link below:\r\n\r\nhttp://example.com/password_resets/IWAHQV67Gyu6BAQUaz9OoA/edit?email=michael%40example.com\r\n\r\nThis link will expire in tow hours.\r\n\r\nIf you did not request your password to be reset, please ignore this email and your password will stay as it is.\r\n\r\n\r\n----==_mimepart_596197d92db13_182bcc70e015864\r\nContent-Type: text/html;\r\n charset=UTF-8\r\nContent-Transfer-Encoding: 7bit\r\n\r\n<!DOCTYPE html>\r\n<html>\r\n <head>\r\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\r\n <style>\r\n /* Email styles need to be inline */\r\n </style>\r\n </head>\r\n\r\n <body>\r\n <h1>Password reset</h1>\r\n\r\n<p>To reset your password click the link below:</p>\r\n\r\n<a href=\"http://example.com/password_resets/IWAHQV67Gyu6BAQUaz9OoA/edit?email=michael%40example.com\">Reset password</a>\r\n\r\n<p>This link will expire in two hours.</p>\r\n\r\n<p>\r\n If you did not request your password to be reset, please ignore this email and your password will stay as it is.\r\n</p>\r\n\r\n </body>\r\n</html>\r\n\r\n----==_mimepart_596197d92db13_182bcc70e015864--\r\n".
test/mailers/user_mailer_test.rb:25:in `block in <class:UserMailerTest>'
2/2: [=====================================================================================================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.63150s
2 tests, 16 assertions, 1 failures, 0 errors, 0 skips
テスト実行後は元に戻しておく。
おわりに
パスワード再設定メールの総身諸利を実装することができました。
まだ、production環境にデプロイしていないため、実際にパスワード再設定メールが飛ぶかどうかの確認ができていません。(ここは、12.4 本番環境でのメール送信 (再掲)で実施)
今回、develop環境でメールが飛ばないことを失念しており、はまってしまったのでみなさんもご注意ください。。。