railsチュートリアル第１１章 AccountActivationのデータモデル

###AccountActivationのデータモデル
```
ubuntu:~/environment/sample_app (account-activation) $ rails generate migration add_activation_to_users activation_digest:string activated:boolean activated_at:datetime
Running via Spring preloader in process 4751
      invoke  active_record
      create    db/migrate/20211017043743_add_activation_to_users.rb
```
####Activationトークンのコールバック
####アカウント有効化用の属性とインデックスを追加するマイグレーション
db/migrate/[timestamp]_add_activation_to_users.rb

```rb
class AddActivationToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :activation_digest, :string
    add_column :users, :activated, :boolean, default: false
    # activated属性のデフォルトの論理値をfalseにしておきます
    # 仮想属性の有効化トークンにアクセス
    add_column :users, :activated_at, :datetime
  end
end
```

###Userモデルにアカウント有効化のコードを追加する 
app/models/user.rb

```rb
class User < ApplicationRecord
  attr_accessor :remember_token, :activation_token
  before_save   :downcase_email
  before_create :create_activation_digest
  # トークンとそれに対応するダイジェストを割り当てる
.
.
.
  private
  
  # メールアドレスをすべて小文字にする
  def downcase_email
    self.email = email.downcase
  end

    # 有効化トークンとダイジェストを作成および代入する
  def create_activation_digest
  # Userモデル内でしか使わないので、外部に公開する必要ない。
    self.activation_token  = User.new_token
    self.activation_digest = User.digest(activation_token)
  end
end
```
####サンプルユーザーの生成とテスト
サンプルデータとfixtureも更新し、テスト時のサンプルとユーザーを事前に有効化する
####サンプルユーザーを最初から有効にしておく
db/seeds.rb

```rb
# メインのサンプルユーザーを1人作成する
User.create!(name:  "Example User",
             email: "example@railstutorial.org",
             password:              "foobar",
             password_confirmation: "foobar",
             admin: true,
             activated: true,
             activated_at: Time.zone.now)
# create!は基本的にcreateメソッドと同じものですが、
#   ユーザーが無効な場合にfalseを返すのではなく例外を発生させる
# admin:trueにして管理者にする
# サーバーのタイムゾーンに応じたタイムスタンプ

# 追加のユーザーをまとめて生成する
# メイン以外のユーザー99人を作成
99.times do |n|
  name  = Faker::Name.name
  email = "example-#{n+1}@railstutorial.org"
  # 数ごとにメアドが変更される
  password = "password"
  # パスワードは変わらない
  User.create!(name:  name,
               email: email,
               password:              password,
               password_confirmation: password,
               activated: true,
               activated_at: Time.zone.now)
  # 許可された属性リストにadminが含まれていない
  # 任意のユーザーが自分自身にアプリケーションの
  #   管理者権限を与えることを防止
  
end
```
####fixtureのユーザーを有効にしておく
test/fixtures/users.yml

```yml
michael:
  name: Michael Example
  email: michael@example.com
  password_digest: <%= User.digest('password') %>
  admin: true
  activated: true
  activated_at: <%= Time.zone.now %>
  # サーバーのタイムゾーンに応じたタイムスタンプ
  
archer:
  name: Sterling Archer
  email: duchess@example.gov
  password_digest: <%= User.digest('password') %>
  activated: true
  activated_at: <%= Time.zone.now %>
  
lana:
  name: Lana Kane
  email: hands@example.gov
  password_digest: <%= User.digest('password') %>
  activated: true
  activated_at: <%= Time.zone.now %>

malory:
  name: Malory Archer
  email: boss@example.gov
  password_digest: <%= User.digest('password') %>
  activated: true
  activated_at: <%= Time.zone.now %>

<% 30.times do |n| %>
# さらに30人のユーザーを追加
user_<%= n %>:
  name:  <%= "User #{n}" %>
  email: <%= "user-#{n}@example.com" %>
  password_digest: <%= User.digest('password') %>
  activated: true
  activated_at: <%= Time.zone.now %>
<% end %>
```

###演習
1.
本項での変更を加えた後、テストスイートが green のままになっていることを確認してみましょう。

```
ubuntu:~/environment/sample_app (account-activation) $ rails t
Running via Spring preloader in process 9538
Started with run options --seed 13465

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

Finished in 3.52011s
43 tests, 168 assertions, 0 failures, 0 errors, 0 skips
```

2.
コンソールからUserクラスのインスタンスを生成し、そのオブジェクトからcreate_activation_digestメソッドを呼び出そうとすると（Privateメソッドなので）NoMethodErrorが発生することを確認してみましょう。また、そのUserオブジェクトからダイジェストの値も確認してみましょう。

```
ubuntu:~/environment/sample_app (account-activation) $ rails console
Running via Spring preloader in process 9590
Loading development environment (Rails 6.0.3)
>> User.create_activate_digest
Traceback (most recent call last):
        1: from (irb):1
NoMethodError (undefined method `create_activate_digest' for User (call 'User.connection' to establish a connection):Class)
```

3.
リスト 6.34で、メールアドレスの小文字化にはemail.downcase!という（代入せずに済む）メソッドがあることを知りました。このメソッドを使って、リスト 11.3のdowncase_emailメソッドを改良してみてください。また、うまく変更できれば、テストスイートは成功したままになっていることも確認してみてください。

```rb
class User < ApplicationRecord
.
.
.
  #private
  
  # メールアドレスをすべて小文字にする
    def downcase_email
      email.downcase!
    end
.
.
.
end
```

```
ubuntu:~/environment/sample_app (account-activation) $ rails t
Running via Spring preloader in process 11264
Started with run options --seed 11907

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

Finished in 2.14029s
43 tests, 168 assertions, 0 failures, 0 errors, 0 skips
```