らくだ🐫にもできるRailsチュートリアル|11.2

11.2 アカウント有効化のメール送信

準備ができたので、アカウント有効化メールに必要なコードを追加していく

このメソッドではAction Mailerライブラリを使ってUserのメイラーを追加します。このメイラーはUsersコントローラのcreateアクションで有効化リンクをメール送信するために使います。

Action Mailerライブラリとなはんぞ

Railsを使ってメールを送信する仕組み(雑)
アクションやviewからメールを送信できるようになる
メイラーの動作はコントローラのアクションと似ているしテンプレートはviewに似ている
詳しくはこちらとか→Railsガイド|Action Mailer の基礎

11.2.1 送信メールのテンプレート

メイラーもrails generateで生成する

この章で必要なaccount_activationメソッドと12章で必要なpassword_resetメソッドが生成されている(app/mailers/user_mailer.rb内)
また、ビューのテンプレートがテキストメール用とHTMLメール用の2つずつ生成されている

生成されたメイラー

生成されたUserメイラー

メイラーをカスタマイズしていく

メイラーのview

テンプレートビューは通常のビューと同じでERBで自由にカスタマイズできる。

viewに含めるコード

ユーザー名を含む挨拶文と有効化リンクを追加する。
→Railsサーバーでユーザーをメールアドレスで検索して有効化トークンを認証できるようにするため、リンクにはメールアドレスとトークンを両方含めておく必要があります

URLで使えるようにBase64でエンコードされています。これはちょうど/users/1/editの「1」のようなユーザーIDと同じ役割を果たします。このトークンは、特にAccountActivationsコントローラのeditアクションではparamsハッシュでparams[:id]として参照できます。

さらにクエリパラメータを使ってメールアドレスを組み込む

クエリパラメータとはなんぞ

クエリパラメータとは、URLの末尾で疑問符「?」に続けてキーと値のペアを記述したものです

上記で言えばedit?email=foo%40example.comの部分
edit?に続けてキー「email」値「foo%40example.com」を呼んでいる
「%40」は「@」のエスケープなので実際呼び出しているのは「foo@example.com」
Railsでクエリパラメータを設定するには、名前付きルートに対して次のようなハッシュを追加する

こうすることでRailsが特殊な文字を自動的にエスケープしてくれるし、コントローラでparams[:email]からメールアドレスを取り出すときには、自動的にエスケープを解除してくれる。優しい。

アカウント有効化メールのview

mailers/user_mailer.rbで定義した@userインスタンス変数、editへの名前付きルート、ERBを組み合わせて、必要なリンクを作成する

演習

  1. コンソールを開き、CGIモジュールのescapeメソッド (リスト 11.15) でメールアドレスの文字列をエスケープできることを確認してみましょう。このメソッドで”Don’t panic!”をエスケープすると、どんな結果になりますか?

11.2.2 送信メールのプレビュー

Railsでは、特殊なURLにアクセスするとメールのメッセージをその場でプレビューすることができます。メールを実際に送信しなくてもよいので大変便利です。これを利用するには、アプリケーションのdevelopment環境の設定に手を加える必要があります

developmentサーバーを再起動して設定を読み込んだらUserメイラーのプレビューファイルを更新する

以上で指定のURLでアカウント有効化メールをプレビューできる!

演習

  1. Railsのプレビュー機能を使って、ブラウザから先ほどのメールを表示してみてください。「Date」の欄にはどんな内容が表示されているでしょうか?
  1. アクセスした日時

11.2.3 送信メールのテスト

プレビューのテストを作成する
自動生成されているテストを利用すれば割と簡単との事

assert_matchとはなんぞ

たびたび出てくるアサーションというヤツ
Railsガイドで見る

assert_match( regexp, string, [msg] ) → stringは正規表現 (regexp) にマッチすると主張する。

正規表現で文字列をテストできるメソッド

メイラーのプレビューのテストを実装

(日本語化しているので本文と多少違います)

mail.body.encodedとは何ぞ

メール本文をメールの本文を(US-ASCIIに)エンコード
で、テストの前にテストファイル内のドメイン名を正しく設定する

しかしリスト11.20のテストはREDなのです!

テストの結果

よくわからないのだけど文字コードがマッチしないって感じです?と思ったので

帰ってきたエラーはこう

→mail.bodyを(暗黙で)string(文字列)に変換する方法がないよ
変換は必要な模様。
そして最初のエラー文でググってみましたところ見つけたのがこちらなど


Rubyは基本UTF-8なので比較元(第一引数)はUTF-8だけど、比較先(第2引数)をわざわざUS-ASCIIにエンコードしてるからエラーになる
なのでUTF-8にエンコードして比較しますって感じですね。
上記を参照に該当部分を書き換え

テストの結果がこれ

マッチするものがありません。って感じですよね🤔
bodyの中身が見えていない状態。ということのようです。
実はここまでテストのドメインホストを本文通りに設定していて、自分の環境に合わせていなかったのでそのせい!!って思ったりもしたんだけど
修正しても結果は変わらずだったのでした。
なのでやり直し。
エラー文でググった中でもうイッコ気になった記事がこちら


メールはTEXTメールとHTMLメールがあるから別々に指定しているのかー。
なんか解説的なものないかな?と思ったところでRailsガイドを見ればいいんじゃないですかね?!と思い立つ🐫
そして参考になる部分に出会いました!
Railsガイド|12.2.2 基本的なテストケース

email.body.to_sは、HTMLまたはテキストで1回出現した場合にのみ存在するとみなされます。メイラーがどちらも提供している場合は、 email.text_part.body.to_sやemail.html_part.body.to_sを用いてそれぞれの一部に対するフィクスチャをテストできます。

と、いう訳で、本文にのっとりコードを書き換え

テスト結果はこう

emailじゃなくてmailでした!
直したらテストが通ったよ!!
そこで疑問なんだけど、ちゃんと場所を指定してあげれば通るって事?
なので元々のテストコード mail.body.encoded にそれぞれtext_partとhtml_partを追加してみました
最終的なテストコードはこうなった

こちらもGREEN!
「じゃぁ最初のExpected /Michael\ Example/ to match # encoding: US-ASCIIは何だったの?」ってお気持ちはあるけど
メールのプレビューも意図した形になってるし、これで行くことにしましょうそうしましょう🐫

演習

動作確認のみにて省略

11.2.4 ユーザーのcreateアクションを更新

createアクションを完成させて実際にメイラーを使えるようにする!

登録時のリダイレクトの挙動が変更されている点にご注意ください。変更前は、ユーザーのプロフィールページ (7.4) にリダイレクトしていましたが、アカウント有効化を実装するうえでは無意味な動作なので、 リダイレクト先をルートURLに変更してあります。

createアクションにアカウント有効化のコードを追加

テストは以前のままなので現状ではRED
あとで修正するので該当部分をいったんコメントアウトしておく
(本文とちょっと違うけどキニシナイ!!)

この状態で新規ユーザーの登録をしてみる!
rootにリダイレクトされて指定したflashメッセージが表示されている

(動作としては)メールが送信されているのがサーバーログ上で確認できる

ログが文字化けしている件

チュートリアル1週目の時にもユーザー名を日本語にすると化けるっていうのがあって
この時は深追いせずにユーザー名に日本語を使わないで進めたのだけど
今回、本文の日本語化も行っている影響でユーザー名をアルファベットにしても文字化けが発生して
ユーザー名をアルファベット表記にしても認証用のアドレスが読めない状況です。
対策を調べたところ、Railsのバージョンが古いもの向けのやり方しか見つけられなかったり
テスト環境では化けるけど本番環境では大丈夫だったとのご意見も見つけたりしたので
ひとまず進めてしまおうと思います。
詰まったらその時考えるってことで!

演習

  1. 新しいユーザーを登録したとき、リダイレクト先が適切なURLに変わったことを確認してみましょう。その後、Railsサーバーのログから送信メールの内容を確認してみてください。有効化トークンの値はどうなっていますか?
  2. コンソールを開き、データベース上にユーザーが作成されたことを確認してみましょう。また、このユーザーはデータベース上にはいますが、有効化のステータスがfalseのままになっていることを確認してください。
  1. リダイレクト先はrootに設定されている
    有効化トークンの値は暗号化されている(はず!)
  2. 動作確認のみにて省略

まとめとか感想

今回は本文に出てこないエラーに悩まされました!
まるっと解決できないまま進むのもちょっと怖い気もするけど
そういうこともあると思うので頑張りたい!

らくだ🐫にもできるRailsチュートリアルとは

「ド」が付く素人のらくだ🐫が勉強するRailsチュートリアルの学習記録です。
自分用に記録していますが、お役に立つことがあれば幸いです。

調べたとはいえらくだ🐫なりの解釈や説明が含まれます。間違っている部分もあるかと思います。そんな所は教えて頂けますと幸いなのですが、このブログにはコメント機能がありません💧お手数おかけしますがTwitterなどでご連絡いただければ幸いです