35歳だけどRailsチュートリアルやってみた。[第4版 11章 11.3 アカウントを有効化する まとめ&解答例]

#はじめに
最近、プロジェクト管理業務が業務の大半を占めており、
プログラムを書く機会がなかなかありません。

このままだとプログラムがまったく書けない人になってしまう危機感（迫り来る35歳定年説）と、
新しいことに挑戦したいという思いから、
[Ruby on Rails チュートリアル実例を使ってRailsを学ぼう 第4版](https://railstutorial.jp/)を学習中です。
業務で使うのはもっぱらJavaなのですが、Rails楽しいですね。


これまでEvernoteに記録していましたが、ソースコードの貼付けに限界を感じたため、
Qiitaで自分が学習した結果をアウトプットしていきます。

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

##動作環境
- cloud9
- ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
- Rails 5.0.0.1

##11.3.1 authenticated?メソッドの抽象化
###本章での学び

####sendメソッドによるメタプログラミング
sendメソッドを使うことで、プログラム内で呼び出すメソッドを動的に決めることができる。
「黒魔術」と言われているらしいw

rubyリファレンスは以下の通り。
[instance method Object#__send__](https://docs.ruby-lang.org/ja/2.3.0/method/Object/i/__send__.html)

>オブジェクトのメソッド name を args を引数に して呼び出し、メソッドの実行結果を返します。

以下の呼び出し方は、どれも`a.length`を呼び出している。
メソッド名を、シンボル`:length`や文字列`"length"`で指定することで、呼び出すメソッドを動的に指定している。

```irb
yokoyan:~/workspace/sample_app (account-activation) $ rails console
Running via Spring preloader in process 1744
Loading development environment (Rails 5.0.0.1)
>> a = [1, 2, 3]
=> [1, 2, 3]
>> a.length
=> 3
>> a.send(:length)
=> 3
>> a.send("length")
=> 3
```

シンボルや文字列ではなく、メソッド名を直接指定すると、エラーになる。

```irb
>> a.send(length)
NameError: undefined local variable or method `length' for main:Object
```

同様に、ユーザー情報の有効化トークンも、sendメソッドで取得できる。
シンボル`:activation_digest`や、文字列`"activation_digest"`を指定することで、`user.activation_digest`を呼び出している。

```irb
yokoyan:~/workspace/sample_app (account-activation) $ rails console
Running via Spring preloader in process 1763
Loading development environment (Rails 5.0.0.1)
>> user = User.first
  User Load (0.2ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-06-20 04:07:12", updated_at: "2017-06-20 04:07:12", password_digest: "$2a$10$No5Z7APSsWojYME0Cm1POerj89GopLI23E2dN/9gyvt...", remember_digest: nil, admin: true, activation_digest: "$2a$10$ufdL0hGRXuEm9biMP3H0deF99cC.BpPrrobGbyL4FQ/...", activated: true, activated_at: "2017-06-20 04:07:12">
>> user.activation_digest
=> "$2a$10$ufdL0hGRXuEm9biMP3H0deF99cC.BpPrrobGbyL4FQ/QOr0USsdKy"
>> user.send(:activation_digest)
=> "$2a$10$ufdL0hGRXuEm9biMP3H0deF99cC.BpPrrobGbyL4FQ/QOr0USsdKy"
>> user.send("activation_digest")
=> "$2a$10$ufdL0hGRXuEm9biMP3H0deF99cC.BpPrrobGbyL4FQ/QOr0USsdKy"
```

シンボルを指定して、式展開でも取得できる。
Railsではシンボルを使うことが一般的。

```irb
?> attribute = :activation
=> :activation
>> user.send("#{attribute}_digest")
=> "$2a$10$ufdL0hGRXuEm9biMP3H0deF99cC.BpPrrobGbyL4FQ/QOr0USsdKy"
```

####【model】authenticated?メソッドの抽象化
Userモデルのauthenticated?メソッド内の`digest`を、sendメソッドを使って動的に変化するようにリファクタリングする。

- sendメソッドに渡すシンボルは、`atribute`として引数に追加する。
- もう1つの引数である`token`は他の認証でも使えるように、名称を一般化している。
- sendメソッドは、`self.send`でも呼べるが、Userモデル内であるため省略している。

```/sample_app/app/models/user.rb
  # 渡されたトークンがダイジェストと一致したらtrueを返す
  def authenticated?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end
```

####動作確認
現時点でテストコードはredになる。
authenticated?メソッドの引数が1つから2つに増えているため、
テストコードで`ArgumentError`が発生している。

```irb
yokoyan:~/workspace/sample_app (account-activation) $ rails test
Running via Spring preloader in process 2906
Started with run options --seed 40151

ERROR["test_current_user_returns_nil_when_remember_digest_is_wrong", SessionsHelperTest, 0.13959716499084607]
 test_current_user_returns_nil_when_remember_digest_is_wrong#SessionsHelperTest (0.14s)
ArgumentError:         ArgumentError: wrong number of arguments (given 1, expected 2)
            app/models/user.rb:42:in `authenticated?'
            app/helpers/sessions_helper.rb:29:in `current_user'
            test/helpers/sessions_helper_test.rb:17:in `block in <class:SessionsHelperTest>'

ERROR["test_current_user_returns_right_user_when_session_is_nil", SessionsHelperTest, 0.14938249200349674]
 test_current_user_returns_right_user_when_session_is_nil#SessionsHelperTest (0.15s)
ArgumentError:         ArgumentError: wrong number of arguments (given 1, expected 2)
            app/models/user.rb:42:in `authenticated?'
            app/helpers/sessions_helper.rb:29:in `current_user'
            test/helpers/sessions_helper_test.rb:11:in `block in <class:SessionsHelperTest>'

ERROR["test_authenticated?_should_return_false_for_a_user_with_nil_digest", UserTest, 0.17042131099151447]
 test_authenticated?_should_return_false_for_a_user_with_nil_digest#UserTest (0.17s)
ArgumentError:         ArgumentError: wrong number of arguments (given 1, expected 2)
            app/models/user.rb:42:in `authenticated?'
            test/models/user_test.rb:75:in `block in <class:UserTest>'

  43/43: [======================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.42911s
43 tests, 181 assertions, 0 failures, 3 errors, 0 skips
```

####【helper】authenticated?を使用するコードの修正
ヘルパー内で、authenticated?メソッドの呼び出し方法を修正する。

```/sample_app/app/helpers/sessions_helper.rb
  # 現在のログイン中のユーザーを返す（いる場合）
  def current_user
      ・・・省略・・・
      # if user && user.authenticated?(cookies[:remember_token])
      if user && user.authenticated?(:remember, cookies[:remember_token])
```

####【test】authenticated?を使用するコードの修正
テストコード内で、authenticated?メソッドの呼び出し方法を修正する。

```/sample_app/test/models/user_test.rb
  test "authenticated? should return false for a user with nil digest" do
    # assert_not @user.authenticated?('')
    assert_not @user.authenticated?(:remember,'')
  end
```

####動作確認
テストがgreenに変わったことを確認。

```irb
yokoyan:~/workspace/sample_app (account-activation) $ rails test
Running via Spring preloader in process 3415
Started with run options --seed 1233

  43/43: [======================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.13016s
43 tests, 185 assertions, 0 failures, 0 errors, 0 skips
```

###演習1
*コンソール内で新しいユーザーを作成してみてください。新しいユーザーの記憶トークンと有効化トークンはどのような値になっているでしょうか? また、各トークンに対応するダイジェストの値はどうなっているでしょうか?*

新規ユーザーを作成する。
コンソール内でユーザーを作成すると、記憶トークンはnilになる。

```irb
yokoyan:~/workspace/sample_app (account-activation) $ rails console --sandbox
Running via Spring preloader in process 3624
Loading development environment in sandbox (Rails 5.0.0.1)
Any modifications you make will be rolled back on exit
>> user = User.create(name: "test3", email: "test3@example.com", password: "password", password_confirmation: "password")
   (0.1ms)  SAVEPOINT active_record_1
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "test3@example.com"], ["LIMIT", 1]]
  SQL (0.4ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at", "password_digest", "activation_digest") VALUES (?, ?, ?, ?, ?, ?)  [["name", "test3"], ["email", "test3@example.com"], ["created_at", 2017-06-25 01:14:20 UTC], ["updated_at", 2017-06-25 01:14:20 UTC], ["password_digest", "$2a$10$9q.TlsyWqdVeeqJce12.1eeunUufSNvkh/LoZo4/6ruphM/Suwxse"], ["activation_digest", "$2a$10$LB2zw3e8q/KYc5eeQxpsMO15pW8yOQXZp.stDZ6aE9ziAttt9Klui"]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> #<User id: 102, name: "test3", email: "test3@example.com", created_at: "2017-06-25 01:14:20", updated_at: "2017-06-25 01:14:20", password_digest: "$2a$10$9q.TlsyWqdVeeqJce12.1eeunUufSNvkh/LoZo4/6ru...", remember_digest: nil, admin: false, activation_digest: "$2a$10$LB2zw3e8q/KYc5eeQxpsMO15pW8yOQXZp.stDZ6aE9z...", activated: nil, activated_at: nil>
>> 
```

そのため、ユーザー作成後に記憶トークンと記憶ダイジェストを更新する。

```irb
?> user.remember_token = User.new_token
=> "g65Xv0B5Sh6HEnxRxGn3Cg"
>> user.update_attribute(:remember_digest, User.digest(user.remember_token))
   (0.1ms)  SAVEPOINT active_record_1
  SQL (0.2ms)  UPDATE "users" SET "updated_at" = ?, "remember_digest" = ? WHERE "users"."id" = ?  [["updated_at", 2017-06-25 01:20:32 UTC], ["remember_digest", "$2a$10$AVQ.XYFSP6eapVywUwO/7.gaE/OHfHqiBJ8q/Rx80MiiWB3A.T2.S"], ["id", 102]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> true
```

記憶トークン、記憶ダイジェスト、有効化トークン、有効化ダイジェストの値を確認。

```irb
?> user.remember_token
=> "g65Xv0B5Sh6HEnxRxGn3Cg"
>> user.remember_digest
=> "$2a$10$AVQ.XYFSP6eapVywUwO/7.gaE/OHfHqiBJ8q/Rx80MiiWB3A.T2.S"
>> user.activation_token
=> "Z8FAIp08GJ6NfxM2CwIznA"
>> user.activation_digest
=> "$2a$10$LB2zw3e8q/KYc5eeQxpsMO15pW8yOQXZp.stDZ6aE9ziAttt9Klui"
```

###演習2
*リスト 11.26で抽象化したauthenticated?メソッドを使って、先ほどの各トークン/ダイジェストの組み合わせで認証が成功することを確認してみましょう。*

先ほど生成したユーザーの記憶トークンを使って、認証結果がtrueになることを確認。

```irb
?> user.authenticated?(:remember, user.remember_token)
=> true
```

##11.3.2 editアクションで有効化
###本章での学び
AccountActivationsコントローラ内で、
前章で作成したauthenticated?メソッドを呼び出すeditアクションを作成する。
これにより、有効化リンクをクリックした後の処理が完成する。

####【controller】editアクションの実装
AccountActivationsController内のeditアクションを実装する。

- ユーザーをemailで検索する
- ユーザーが存在する、かつ、有効化されていないユーザー、かつ、有効化トークンによる認証ができる
    - すべての条件を満たす場合
        - 有効化ステータスをtrueに更新する
        - 有効化時刻を現在時刻で更新する
        - ユーザーをログイン状態にする
        - フラッシュメッセージにsuccessをセットする
        - ユーザー情報ページへリダイレクトする
    - すべての条件を満たさない場合
        - フラッシュメッセージにdangerをセットする
        - ルートURLにリダイレクトする

```/sample_app/app/controllers/account_activations_controller.rb
  def edit
    user = User.find_by(email: params[:email])
    if user && !user.activated? && user.authenticated?(:activation, params[:id])
      user.update_attribute(:activated, true)
      user.update_attribute(:activated_at, Time.zone.now)
      log_in(user)
      flash[:success] = "Account Activated!"
      redirect_to user
    else
      flash[:danger] = "Invalid activation link"
      redirect_to root_url
    end
  end
```

####【controller】sessionsコントローラの改良
ユーザー認証を行うcreateアクションを修正する。
有効化に成功しているユーザーのみログインを行い、有効ではないユーザーがログインできないように修正を加える。

- 有効化されたユーザーか判定する
    - 有効化されている
        - ログインする
        - セッションパラメータのremember_meの値が1なら、ユーザ情報を記憶する（1以外なら忘れる）
        - ログイン前にユーザーがいた場所にリダイレクトする
    - 有効化されていない
        - アカウントが認証されていない旨のメッセージを代入
        - emailの有効化リンクをチェックする旨のメッセージを代入
        - フラッシュメッセージにwarningをセットする
        - ルートURLにリダイレクトする

```/sample_app/app/controllers/sessions_controller.rb
    if @user && @user.authenticate(params[:session][:password])
      if @user.activated?
        #ユーザログイン後にユーザ情報のページヘリダイレクトする
        log_in(@user)
        #チェックされていたらユーザを記憶する
        params[:session][:remember_me] == '1' ? remember(@user) : forget(@user)
        # redirect_to @user
        redirect_back_or @user
      else
        message = "Account note activated."
        message += "Check your email for the activation link."
        flash[:warning] = message
        redirect_to root_url
      end
    else
```

####動作確認
ブラウザを起動して、新規ユーザー（メールアドレスがtest3@example.com）を登録する。

![image](https://qiita-image-store.s3.amazonaws.com/0/98130/97097c00-b0aa-8ec6-5b2a-fe1d9c22c3af.png)

送信されたメールの内容を確認。

```irb
----==_mimepart_595027e48692f_6bd2244f0865b4
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

Hi test3

Welcome to the Sample App! Click on the link below to active your account:

https://rails-tutorial-yokoyan.c9users.io/account_activations/aIUAKDQ_Dy-k1ihCxVCs1A/edit?email=test3%40example.com



----==_mimepart_595027e48692f_6bd2244f0865b4
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>Sample App</h1>

<p>Hi test3</p>,

<p>
  Welcome to the Sample App! Click on the link below to activate your account:
</p>

<a href="https://rails-tutorial-yokoyan.c9users.io/account_activations/aIUAKDQ_Dy-k1ihCxVCs1A/edit?email=test3%40example.com">Activate</a>

  </body>
</html>
```

有効化URLをクリックする前にログインすると、警告メッセージが表示されることを確認。

![image](https://qiita-image-store.s3.amazonaws.com/0/98130/6c18bbbe-906d-70f4-61ad-ccab57e89d70.png)

メール内の有効化URLにアクセスすると、ユーザーが有効化されることを確認。

![image](https://qiita-image-store.s3.amazonaws.com/0/98130/2418f9c8-edc1-ca96-936f-24a23b341668.png)


###演習1
*コンソールから、11.2.4で生成したメールに含まれているURLを調べてみてください。URL内のどこに有効化トークンが含まれているでしょうか?*

有効化トークンが含まれているのは、`account_activations/`の後ろの部分。

```irb
https://rails-tutorial-yokoyan.c9users.io/account_activations/aIUAKDQ_Dy-k1ihCxVCs1A/edit?email=test3%40example.com
```

###演習2
*先ほど見つけたURLをブラウザに貼り付けて、そのユーザーの認証に成功し、有効化できることを確認してみましょう。また、有効化ステータスがtrueになっていることをコンソールから確認してみてください。*

上記の動作確認を参照。
また、コンソールから有効化ステータスがtrueになっていることを確認。

```irb
>> user = User.find_by(email: "test3@example.com")
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "test3@example.com"], ["LIMIT", 1]]
=> #<User id: 102, name: "test3", email: "test3@example.com", created_at: "2017-06-25 21:15:15", updated_at: "2017-06-25 21:21:49", password_digest: "$2a$10$NubRAD6eWQO6NtC2CPKfb.BvH2lchppXa80YEAUalzI...", remember_digest: nil, admin: false, activation_digest: "$2a$10$3S210A5wksNnbfTcFtPEduxCfEhvPiOpB95OHwZ3bM9...", activated: true, activated_at: "2017-06-25 21:21:49">
>> 
?> user.activated?
=> true
```

##11.3.3 有効化のテストとリファクタリング
###本章での学び
アカウント有効化の統合テストを追加する。

####【test】統合テストの修正

- setupで配列deliveriesを初期化する

```/sample_app/test/integration/users_signup_test.rb
  def setup
    ActionMailer::Base.deliveries.clear
  end
```

- GETでsignup_pathにアクセスする
- User.countが1増えていること
    - post users_path , パラメータ
- 配信されたメッセージが1と等しいか確認
- createアクション内のインスタンス変数@userにアクセスしてユーザー情報を取得する
- ユーザーが有効化されていないことを確認
- （有効化されていない状態で）ログインする
- ログインできないことを確認
- GETでedit_account_activation_pathにアクセスする
    - 引数１：無効なトークン
    - 引数２：ユーザーのemail
- ログインできないことを確認
- GETでedit_account_activation_pathにアクセスする
    - 引数１：ユーザーの有効化トークン
    - 引数２：不正なemail
- ログインできないことを確認
- GETでedit_account_activation_pathにアクセスする
    - 引数１：ユーザーの有効化トークン
    - 引数２：ユーザーのemail
- ユーザーをDBから再読み込みして、有効化されていることを確認
- リダイレクトする
- ユーザープロフィール画面のテンプレートが表示されること
- ログインできることを確認

```/sample_app/test/integration/users_signup_test.rb
  test "valid signup information with account activation" do
    get signup_path
    assert_difference 'User.count', 1 do
      post users_path, params: { user: { name: "Example User",
                                          email: "user@example.com",
                                          password: "password",
                                          password_confirmation: "password" } }
    end
    assert_equal 1, ActionMailer::Base.deliveries.size
    user = assigns(:user)
    assert_not user.activated?
    log_in_as(user)
    get edit_account_activation_path("invalid token", email: user.email)
    assert_not is_logged_in?
    get edit_account_activation_path(user.activation_token, email: 'wrong')
    assert_not is_logged_in?
    get edit_account_activation_path(user.activation_token, email: user.email)
    assert user.reload.activated?
    follow_redirect!
    assert_template 'users/show'
    assert_not flash.empty?
    assert is_logged_in?
  end
```

####動作確認
テストがgreenになることを確認。

```irb
yokoyan:~/workspace/sample_app (account-activation) $ rails test
Running via Spring preloader in process 2050
Started with run options --seed 1929

  43/43: [===============================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.90977s
43 tests, 193 assertions, 0 failures, 0 errors, 0 skips
```

####【controller】コントローラのリファクタリング1
ユーザー操作の一部を、コントローラからモデルに移す。
コントローラ内で、以下の有効化ステータスを更新する箇所を、モデルに移す。

```/sample_app/app/controllers/account_activations_controller.rb
  def edit
　　　・・・略・・・
      user.update_attribute(:activated, true)
      user.update_attribute(:activated_at, Time.zone.now)
```

Userモデルにアカウントを有効にする`activate`メソッドを作成する。
Userモデル内であるため、`user.`や、`self.`は省略できる。

```/sample_app/app/models/user.rb
  # アカウントを有効にする
  def activate
    update_attribute(:activated, true)
    update_attribute(:activated_at, Time.zone.now)
  end
```

作成したメソッドを呼び出す。

```/sample_app/app/controllers/account_activations_controller.rb
    if user && !user.activated? && user.authenticated?(:activation, params[:id])
      user.activate
```

####【controller】コントローラのリファクタリング2
ユーザー操作の一部を、コントローラからモデルに移す。
コントローラ内で、以下の有効化メールを送信する箇所を、モデルに移す。

Userモデルにアカウントを有効にする`activate`メソッドと、

```/sample_app/app/controllers/users_controller.rb
  def create
　　　・・・略・・・
      UserMailer.account_activation(@user).deliver_now
```

Userモデルに有効化メールを送信する`send_activation_email`メソッドを作成する。
Userモデル自身が引数となるため、`@user`は、`self`となる。

```/sample_app/app/models/user.rb
  # 有効化用のメールを送信する
  def send_activation_email
    UserMailer.account_activation(self).deliver_now
  end
```

作成したメソッドを呼び出す。

```/sample_app/app/controllers/users_controller.rb
  def create
    @user = User.new(user_params)
    if @user.save
      @user.send_activation_email
```

####リファクタリングの結果確認
テストがgreenになることを確認。

```irb
yokoyan:~/workspace/sample_app (account-activation) $ rails test
Running via Spring preloader in process 2304
Started with run options --seed 49015

  43/43: [===============================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.34037s
43 tests, 193 assertions, 0 failures, 0 errors, 0 skips
```

###演習1
*リスト 11.35にあるactivateメソッドはupdate_attributeを２回呼び出していますが、これは各行で１回ずつデータベースへ問い合わせしていることになります。リスト 11.39に記したテンプレートを使って、update_attributeの呼び出しを１回のupdate_columns呼び出しにまとめてみましょう (これでデータベースへの問い合わせが１回で済むようになります)。また、変更後にテストを実行し、 greenになることも確認してください。*

activateメソッドを改良する。

```/sample_app/app/models/user.rb
  # アカウントを有効にする
  def activate
    # update_attribute(:activated, true)
    # update_attribute(:activated_at, Time.zone.now)
    update_columns(activated: true, activated_at: Time.zone.now)
  end
```

テスト結果がgreenになることを確認。

```irb
yokoyan:~/workspace/sample_app (account-activation) $ rails test
Running via Spring preloader in process 2670
Started with run options --seed 12072

  43/43: [===============================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.13286s
43 tests, 193 assertions, 0 failures, 0 errors, 0 skips
```

###演習2
*現在は、/usersのユーザーindexページを開くとすべてのユーザーが表示され、/users/:idのようにIDを指定すると個別のユーザーを表示できます。しかし考えてみれば、有効でないユーザーは表示する意味がありません。そこで、リスト 11.40のテンプレートを使って、この動作を変更してみましょう8。なお、ここで使っているActive Recordのwhereメソッドについては、13.3.3でもう少し詳しく説明します。*

https://xxxxxx/users/2 を表示した後に、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/98130/c17aa12d-f332-59df-e4ad-12cd5a5a718e.png)

https://xxxxxx/users/3 にブラウザのURLを変数すると、アクセスができる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/98130/4163219d-32f9-5551-121b-6eb3c432e903.png)

コントローラを改良する。
有効なユーザーのみ一覧表示する。

```/sample_app/app/controllers/users_controller.rb
  def index
    # @users = User.all
    # @users = User.paginate(page: params[:page])
    @users = User.where(activated: true).paginate(page: params[:page])
  end

  def show
    @user = User.find(params[:id])
    redirect_to root_url and return unless @user.activated?
    #debugger
  end
```

###演習3
*ここまでの演習課題で変更したコードをテストするために、/users と /users/:id の両方に対する統合テストを作成してみましょう。*

- 有効化されていないテストユーザーを作成する

```/sample_app/test/fixtures/users.yml
non_activated:
  name: Non Activated
  email: non_activated@example.gov
  password_digest: <%= User.digest('password') %>
  activated: false
  activated_at: <%= Time.zone.now %>
```

- setup時にテストユーザーを読み込む
    - `@non_activated_user`

```/sample_app/test/controllers/users_controller_test.rb
  def setup
    @user = users(:michael)
    @other_user = users(:archer)
    @non_activated_user = users(:non_activated)
  end
```

- テストケース名を生成
    - 有効化されていない属性を許可しない
- `@non_activated_user`でログインする
- `@non_activated_user`の有効化属性がfalseであること
- getで/usersにアクセスする
- 有効化されていないユーザーが表示されていないこと
    - `@non_activated_user`のプロフィールページへのリンクがユーザー一覧に表示されていないこと
- getで/users/:id（有効化されていないユーザー）にアクセスする
- ルートURLにリダイレクトされること

```/sample_app/test/controllers/users_controller_test.rb
  test "should not allow the not activated attribute" do
    log_in_as(@non_activated_user)
    assert_not @non_activated_user.activated?
    get users_path
    assert_select "a[href=?]", user_path(@non_activated_user), count: 0
    get user_path(@non_activated_user)
    assert_redirected_to root_url
  end
```


#おわりに
アカウントの有効化処理が完成しました。
最後の演習では、ゼロから統合テストを作るのは難しかったですが、
日本語であるべき姿を組み立てると書きやすかったです。

丸写しするのではなく、あるべき姿を常に考えながら、これからもプログラムを書いていきます。