0
1

More than 3 years have passed since last update.

【Rails Tutorial11章】アカウント有効化機能の実装手順を整理してみました【中編】

Last updated at Posted at 2020-04-16

はじめに

Railsチュートリアル11章の内容を、少しでも理解の助けとなればと思い、割としっかり目に整理しました!
備忘録です。

前提

Railsチュートリアル1〜10章までの内容が完了していること。

内容

Railsチュートリアル11章のアカウント有効化機能の実装手順を、前中後半の3回に分けて整理しました。
中編である今回は、アカウント有効化メール送信機能の実装をしていきます!

前編→AccountActivationsリソースの作成
後編→アカウント有効化機能の実装

1.アカウント有効化用のメールを送信する機能の実装

  ●データのモデル化が完了したので、次はアカウント有効化メールの送信に必要な機能を記述していく

  ●メールを送信する機能を実装するには、Action Mailerライブラリを使って、Userのメイラーを作成する必要がある
    ➡︎メイラーは、Usersコントローラのcreateアクションで、ユーザーへ有効化リンクをメール送信させるために使う。

    ➡︎メイラーはコントローラのアクションと似ており、メールのテンプレートを、ビューと同じ要領で定義できる。
      →有効化トークンと有効化するアカウントのアドレスのリンクは、このテンプレートの中で使う。

1-1.送信メールのテンプレートを作成していく

  ●まず、Userメイラーを作成する。
    ➡︎$ rails g mailer UserMailer account_activation password_reset
      →UserMailerはメイラー名で、その後には必要となるメソッドを入力する。
      →password_resetメソッドは、後にパスワード再設定機能を実装する際に使うので、序でに作成しておく。

    ➡︎メイラーを生成すると、ついでにビューのテンプレートがファイルごとに2つ生成される。
      →1つはテキストメール用のテンプレートで、1つはHTMLメール用のテンプレート。

  ●生成されたメイラーをカスタマイズして、有効化メールで使えるようにする。
    ➡Applicationメイラー
      →app/mailers/application_mailer.rb
      →デフォルトでfromアドレスが設定されていると思うが、これを削除して、実際に使えるメールアドレスに書き換える。

    ➡Userメイラー
      →app/mailers/user_mailer.rb
      →コマンドを実行した際に作成したメソッドの内、account_activationメソッドをカスタマイズしていく。
        →まずメソッド名をaccount_activation(user)とし、ユーザーのデータを取得できるよう明示的に引数を記述してあげる。
          →取得したユーザーは、ビューで利用できるように@userインスタンス変数へ代入されるようにする。
          →ユーザーへメールが送信されるよう処理を記述し、件名も付け加えておく。
            →mail to: user.email, subject: "件名"

  ●ユーザーへ送信するための有効化リンクを作成する準備をする
    ➡︎ユーザーをメールアドレスで検索し、有効化トークンを認証できるよう処理を記述していく。

    ➡︎そのためには、リンクにメールアドレスとトークンの両方を組み込む必要がある。
      →アカウントを有効化するリンクにトークンを組み込む方法
        →AccountActivationsリソースにて有効化はモデル化したので、有効化トークンは名前付きルートの引数で使われることになる。
        →つまり、edit_account_activation_url(@user.activation_token)となる。
        →上記の名前付きルートは、下記の形式のURLを生成する。
          →http://www.example.com/account_activations/(new_tokenメソッドで生成されたランダム文字列)/edit
          →ちなみに上記のトークン部分はユーザーIDと同じ働きをするため、AccountActivationsコントローラのeditアクション内で、params[:id]とすれば参照するできる。
      →というわけで、トークンの組み込み完了。
      →今度は、有効化リンクにメールアドレスも組み込む
        →リンクにメールアドレスを組み込むには、クエリパラメータを使う必要がある。
          →クエリパラメータとは、URLの末尾で「?」に続けてキーと値のペアを記述したもの。
          →要するに、http://<省略>/edit?email=user%40example.comみたいな感じ。
          →「%40」の意味は@と一緒。URLでは@記号が使えないので、エスケープと呼ばれる手法により変換している。
        →上記のようにURLにクエリパラメータを組み込むには、名前付きルートにてユーザーのメールアドレスを参照できるようなハッシュを記述してあげればOK。
        →どういうことかというと、edit_account_activation(@user.activation_token, email:@user.email)とすればOK。
        →上記のように名前付きルートでクエリパラメータを書き加えると、Railsが自動的にエスケープを行ってくれため、正常なリンクとして動作してくれる。
        →さらに、editアクションでメールアドレスを参照するためにparams[:email]とする際は、自動的にスケープを解除してくれる。便利。

   ➡︎︎︎これで、リンクを作成する準備が完了した。

  ●テンプレートビューにて、リンクを作成する。
    ➡︎通常のERb同様ビューは自由にカスタマイズできるので、挨拶文にユーザー名を含め、有効化リンクを記述することにする。

    ➡︎︎︎アカウント有効化のテキストビューにて。
      →挨拶とユーザーの名前を表示する記述をする。
      →ERB内でeditへの名前付きルートを使って、有効化トークンとメールアドレスを組み込んだリンクを作成する。

    ➡︎アカウント有効化のHTMLビューにて。
      →挨拶とユーザーの名前を表示する記述をする。
      →ERb内でlink_toタグで、上記同様editへの名前付きルートを使って、有効化トークンとメールアドレスを組み込んだリンクを作成する。

ターミナル
  #1-1.Userメイラーの作成
  $ rails g mailer UserMailer account_activation password_reset
app/mailers/application_mailer.rb
  #1-1.Applicationメイラーのカスタマイズ。
  class ApplicationMailer > ActionMailer::Base
    default from: "実際に有効化メール送信で使うメアド"
    layout 'mailer'
  end
app/mailers/user_mailer.rb
  #1-1.Userメイラーのカスタマイズ。
  class UserMailer < ApplicationMailer
     
    def account_activation(user)
      @user = user
      mail to: user.email, subject "件名"
 
    #省略
  
  end
app/views/user_mailer/account_activation.text.erb
  #1-1.アカウント有効化のテキストビュー。
  こんにちは、<%= @user.name %>
  下記のリンクをクリックして、アカウントを有効化してください。
  <%= edit_account_activation_url(@user.activation_token, 
                                  email: @user.email) %>
app/views/user_mailer/account_activation.html.erb
  #1-1.アカウント有効化のHTMLビュー。
  こんにちは、<%= @user.name %>
  下記のリンクをクリックして、アカウントを有効化してください。
  <%= link_to "有効化する", edit_account_activaation_url(@user.activation_token,
                                                       email: @user.email) %>

1-2.送信メールのプレビュー

  ●メールメッセージをその場で簡単にプレビューする。
    ➡︎アプリケーションのdevelopment環境の設定に手を加える必要がある。
      →config/environments/development.rbファイルへ移動する。
      →ホスト名は、各々のdevelopment環境に合わせて変更する必要があるので注意。
        →例えば、ローカル環境で開発しているなら「'localhost:3000'」に変更しなければ動作しない。
      →developmentサーバーを再起動して、設定を読み込む。

    ➡アカウント有効化のプレビューメソッドを定義する。
      →test/mailers/previews/user_mailer_preview.rbファイルへ移動する。
      →account_activationメソッドはこのままでは動作しないため、動作させるための処理を記述していく必要がある。
        →まず、開発用DBの最初のユーザーを取得するためのuser変数を定義する。
        →さらに、ビューのテンプレートでアカウント有効化のトークンが必要となるため、ユーザーの有効化トークンにUser.new_tokenを代入する処理を記述する必要がある。
          →有効化トークンは、仮の属性なのでDBのユーザーは実際にはこの値を持っているわけではない。
        →上記で取得したユーザーをUserMailer.account_activationメソッドの引数に渡す。

    ➡︎以上のコードを実装したことで、指定のURLでアカウント有効化メールをプレビューできるようになった。

config/environments/development.rb
  #1-2.development環境のメール設定。
  Rails.application.configure do
    .
    .
    .
    config.action_mailer.raise_delivery_errors = true
    config.action_mailer.delivery_method = :test
    host = '各々のホストのURLを記述'
    config.action_mailer.default_url_options = { host: host, protocol: 'https' }
    .
    .
    .
  end
test/mailers/previews/user_mailer_preview.rb
  # Preview all emails at http://localhost:3000/rails/mailers/user_mailer
  class UserMailerPreview < ActionMailer::Preview
 
  # Preview this email at
  # http://localhost:3000/rails/mailers/user_mailer/account_activation
 
  #1-2.アカウント有効化のプレビューメソッド定義。
  def account_activation
    user = User.first
    user.activation_token = User.new_token
    UserMailer.account_activation(user)
  end
  .
  .
  .
end

2-3.送信メールのテストを書いていく

  ●メールプレビューのテストを作成する。
    ➡︎test/mailers/user_mailer_test.rbに、Userメイラーの簡単なテスト例が自動生成されているので利用する。

    ➡︎assert_matchというメソッドがとても便利で、正規表現によって文字列をテストすることができる。
      →例.assert_match 'foo', 'foobar' #true

    ➡︎assert_matchメソッドを使い、名前、有効化トークン、エスケープ済みメールアドレスが本文に含まれているかどうかをテストする。
      →ちなみに、CGI.escapse(use.email)とすることで、テスト用のユーザーのメールアドレスをエスケープすることができる。
      →それから、このCGI.escape部分を削除すると、テストはパスしない。

    ➡︎加えてテストコードのfixtureユーザーに、有効化トークンを取得させる記述をする。そうしないと空白になる。
    ➡︎テストRED。

    ➡︎このテストがパスするには、テストファイル内のドメイン名を正しく設定する必要がある。
      →config/environments/test.rbへ移動。
      →テストのドメインホストを、host: '正しいドメイン名'とする。

    ➡︎テストGREEN。

test/mailers/user_mailer_test.rb
  #1-3.現在までのメール機能実装に関するテストを書いていく。RED。
  require 'test_helper'
  class UserMailerTest < ActionMailer::TestCase
 
  test "account_activation" do
    user = users(:michael)
    user.activation_token = User.new_token  #ここで、有効化トークンを取得しないと空白になるので注意。
    mail = UserMailer.account_activation(user)
    assert_equal "Account activation", mail.subject
    assert_equal [各々が設定したメールアドレスを記述], mail.to
    assert_equal ["noreply@example.com"], mail.from
    assert_match user.name,               mail.body.encoded
    assert_match user.activation_token,   mail.body.encoded
    assert_match CGI.escape(user.email),  mail.body.encoded
  end
end
config/environments/test.rb
  #1-3.テストのドメインホストを設定する。
  Rails.application.configure do
    .
    .
    .
    config.action_mailer.delivery_method = :test
    config.action_mailer.default_url_options = { host: '正しいホストを記述' }
    .
    .
    .
  end

2-4.ユーザーのcreateアクションを更新。

  ●createアクション内のユーザー登録機能に、アカウント有効化機能を追加する。
    ➡︎app/controllers/users_controller.rbファイルへ移動。
      →ユーザーの新規登録が完了しユーザーが保存された後、そのユーザーへアカウント有効化メールを送信する処理を記述する。
        →UserMailer.account_activation(@user).deliver_now
      →ユーザーへメールを確認するよう促すフラッシュを表示させ、リダイレクト先はルートURLに変更。
      →この時同時に、登録が完了するとログインする機能を削除する。

  ●上記の変更により、テストスイートがREDになった。
    ➡︎integration/users_signup_test.rbへ移動。
      →失敗するテストを一旦コメントアウト。
        →新規登録後にログインさせないようにしたので、ユーザープロフページが表示されているかどうかの検証と、ユーザーのログインを検証する記述をコメントアウトにする。
        →assert_template 'users/show'と、assert is_logged_in?
      →アカウント有効化機能を実装した後、テストを書くのでそこで修正する。

app/controllers/users_controller.rb
  class UsersController < ApplicationController
    .
    .
    .
    def create
      @user = User.new(user_params)
      if @user.save
        #1-4.新規登録後、ユーザーへアカウント有効化のメールを送信する。(ログインは削除)
        UserMailer.account_activation(@user).deliver_now
        flash[:info] = "Please check your email to activate your account."
        redirect_to root_url
      else
        render 'new'
      end
    end
    .
    .
    .
end

最後に

 中編のアカウント有効化用メール送信機能の実装が完了しました。
 前編→AccountActivationsリソースの作成
 後編→アカウント有効化機能の実装

参考

 Railsチュートリアル 第11章アカウントの有効化

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1