Railsチュートリアル(第6版)　第6章　ユーザーのモデルを作成する

#第6章
この章はユーザーモデルを作っていく。前章はスタブページまでで終わったが、これからひたすらユーザー登録に関することを学んでいく。
(なんと本章から第12章までひたすら作っていくのでしんどい道となる)
頑張ろう

##Userモデル
ユーザー登録するからユーザー登録用ページを作る前に、まずは名前、メールアドレス、パスワード等を保存するためのデータ構造を作成しなければならない。
このデータ構造を、Railsでは**Model(モデル)**という。
また、データベースとやり取りするためのRailsライブラリは、**Active Record**と呼ばれる。
通常データベースを使うなら、SQLという言語を使うが、Railsではマイグレーション機能で、データベースの構造を切り離してくれるため、SQLを意識しなくてもOK
(この辺りの機能便利だなーと思った。筆者は仕事でSQLを多少なりと触っていた経験があるので、SQLをいじらず作成できるのはでかい）

なおRailsチュートリアルでは、開発環境ではSQLiteを使用し、本番環境はPostgreSQLを使う。


###データベース移行
コンソールでいくつかデータを作成したが、これだけでは永続性が欠けている。ということで、永続性を保つためにモデルを作ることとする。

復習　命名規則
・コントローラー名は、複数形を使う。 例：Users
・モデル名は、単数形を使う。例：User

理由は、コントローラーは様々なデータを持つのに対し、モデルは決まった特定のデータだけを参照するため。

早速、モデルを作成する。

```
$ rails generate model User name:string email:string
```

`name:string`や`email:string`オプションのパラメータを渡し、データベースで使う属性を与えている。

`generate`コマンドを使うと、マイグレーションファイル、テストファイル、フィクスチャを同時に作ってくれる。

マイグレーションファイルを見てみよう。

```ruby:/sample_app/db/migrate/20210523082848_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end
```

タイムスタンプというものが発行されることが分かる。複数の開発者が同じ整数を持つマイグレーションを生成した際に、コンフリクトを起こさないようにするためのもの。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1471120/2c64d668-a99e-f04a-3498-5d95be922ce7.png)
参照：railsチュートリアル

`name`と`email`だけしか属性を与えていないが、他にも`id`と`created_at`と`updated_at`が作られている。
先ほどの`t.timestampsによって`created_at`と`updated_at`というマジックカラムが作成される。作成と更新日時を保持してくれる。

さて、ここまで来たらマイグレーションを適用させよう。

```
$ rails db:migrate
```

ついでに、DB Browser for SQLiteというソフトを使えばデータベースの構造を見れる。

演習
スキーマとマイグレーションファイルの比較

```ruby:/sample_app/db/schema.rb
ActiveRecord::Schema.define(version: 2021_05_23_082848) do

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.string "email"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end
end
```

```ruby:/sample_app/db/migrate/20210523082848_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end
```

2.ロールバック実行

```
$ rails db:rollback
```

ロールバックとはもとに戻すことを意味する。

```
$ rails db:rollback
-- drop_table(:users)
   -> 0.0089s
```

スキーマの内容を見ると、、、

```ruby:/sample_app/db/schema.rb
ActiveRecord::Schema.define(version: 0) do

end
```

`drop_table`コマンドを呼び出し、削除している。`change`メソッドが`create_table`と`drop_table`のコマンドを知っている。

あとは、もう一度`rails db:migrate`すればOK

###modelファイル
第4章で学んだ継承関係をモデルでもみる事ができる。

例えば、Userモデルは下のような感じだ。

```ruby:app/models/user.rb
class User < ApplicationRecord
end
```

class User < ApplicationRecord < ActiveRecord::Baseといった具合に継承している。

演習

```
2.6.3 :001 > User.new
   (4.5ms)  SELECT sqlite_version(*)
 => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil> 
```

`User.new`で`User`クラスのオブジェクトが生成された。

###ユーザーオブジェクト生成
サンドボックスモードでコンソールを起動する。サンドボックスモードはコンソール終了時にすべてロールバックしてくれる。

```
$ rails console --sandbox
```

要点だけ
・`User.new`を使うことで、新しいオブジェクトを生成できる。引数なしで読んだ場合は、全ての属性が`nil`のオブジェクトとなる。

・`user`オブジェクトが有効かどうかを調べるには、`user.valid?`とすることで調べられる。

・保存するには、`save`メソッドを使って、`user.save`として、成功すれば保存する。

・Userモデルのインスタンスの属性にアクセスするには、ドット記法を用いる。
　`user.name`や`user.email`等

・モデルの生成と保存を一度に行える方法がある。それは、`create`メソッドだ。`User.create(name: "値", email: "値")`とすればOK

・`create`の逆でオブジェクトを削除するには、`destroy`メソッドを使うが、オブジェクトはメモリ上に残る。

演習
1.user.nameとuser.emailが、どちらもStringクラスのインスタンスであることを確認

```
>> user.name.class
=> String
>> user.email.class
=> String
```

2.created_atとupdated_atは、どのクラスのインスタンスか。

```
>> foo.created_at.class
=> ActiveSupport::TimeWithZone
>> foo.updated_at.class
=> ActiveSupport::TimeWithZone
```

###ユーザーオブジェクトを検索する
Active Recordはオブジェクトを検索するための方法がいくつもある。

・1番目のユーザーを探す。`User.find(id)`

```
>> User.find(1)
```

番号を変えれば、その番号に該当するユーザーが取得できる。

・属性と検索値で探す。`User.find_by(属性: "値")`

```
>> User.find_by(email: "michael@example.com")
```

・最初のユーザーを検索する。`User.first`
　データベースの最初のユーザーを返す。

```
>> User.first
```

・デーベースの全てのユーザーを返す。`User.all`

```
>> User.all
```

全てのオブジェクトのクラスが`ActiveRecord::Relation`となっており、各オブジェクトを配列としてまとめてくれている。
つまりは`ActiveRecord::Relation`クラスで、各オブジェクトを配列という扱いで返してくれるようになっている。

演習

```
>> User.all.class
=> User::ActiveRecord_Relation
```

```
>> User.all.length
```

###ユーザーオブジェクトを更新する。
ユーザーオブジェクトを更新する方法は２通りある。

１つ目
属性を個別に代入する方法

```
>> user.name = "ZIP"
=> "ZIP"
>> user.save
```

この方法を必ずsaveを実行する必要がある。saveを行わずreloadすると元のオブジェクトを再読み込みするので、変更が取り消される。

２つ目
`update`を使う方法

```
>> user.update(name: "The Dude", email: "dude@abides.org")
```

`update`メソッドは属性のハッシュを受け取り、成功した時は更新と保存を同時にしてくれる。しかし、検証に一つでも失敗すれば、`update`の呼び出しは失敗する。
また、特定の属性のみ更新したい場合は、`update_attribute`とすることで、検証を回避することができる。

```
>> user.update_attribute(:name, "El Duderino")
```

##ユーザーを検証する
`name`と`email`属性が与えられたUserモデルを作ってきた。
しかし、現時点ではどんなデータも入力できてしまう。
`name`なら、空白とかめっちゃ長い名前とか
`email`なら、空白は当然ながら、メールアドレスのフォーマットに従ってないやつとか。
これらを解決しようってのが、**検証(Validation)**という訳。

検証でよく使われるやつ
・存在性(presence)
・長さ(length)
・フォーマット(format)
・一意性(uniqueness)
・確認(confirmation)

###有効性を検証する
検証が正しく動作しているかを進めるにあたり、テスト駆動開発で行っていく。
今までのように失敗→成功という順序。

テスト方法
①有効なモデルのオブジェクトを生成
②その属性のうち一つを有効でない属性に意図的に変更
③バリデーションで失敗するかどうかのテストをする

ユーザーモデルのテスト

```ruby:test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase

  def setup
    @user = User.new(name: "Example User", email: "user@example.com")
  end

  test "should be valid" do
    assert @user.valid?
  end
end
```

`setup`メソッドを使って、`@user`を作成する。setupメソッド内に書かれた処理は、各テストが走る直前に実行される。
また、`@user`はインスタンス変数だが、setupメソッド内で宣言したため、全てのテストでこのインスタンス変数が使えるようになる。
`valid?`メソッドを使い、Userオブジェクトの有効性をテストできればOK。

```
$ rails test:models
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
```

モデルに関係するテストだけ実行している。まだUserモデルにバリデーションがないので、テストは成功している。

###存在性を検証する
基本と言っていい「存在性(Presence)」というバリデーション。
これは、渡された属性が存在するかどうかを検証するもの。
存在性のバリデーションがあれば、渡された属性にデータがあるということを保証できる。

`name`属性の存在性テストを追加

```ruby:test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase

  def setup
    @user = User.new(name: "Example User", email: "user@example.com")
  end

  test "should be valid" do
    assert @user.valid?
  end

  test "name should be present" do
    @user.name = "     "
    assert_not @user.valid?
  end
end
```

テストする

```
$ rails test:models
2 runs, 2 assertions, 1 failures, 0 errors, 0 skips
```

次にバリデーションを追加する。

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
end
```

このバリデーション記法は丸カッコと波カッコが省略されている。
省略せずにかくとこんな感じ
`validates(:name, {presence: true})`
validatesメソッドの第一引数に、ハッシュのキー`:name`を渡し、第二引数にオプションハッシュを渡している。メソッドの丸カッコは省略できる＆メソッド引数の最後のハッシュは省略できる。

コンソールでやるとこんな感じ

```
$ rails console --sandbox
>> user = User.new(name: "", email: "michael@example.com")
>> user.valid?
=> false
```

名前の属性が空白になっているため、存在性の検証でfalseが返ってきている。1つ以上失敗した時、falseを返す。
逆にすべてのバリデーションがOKならtrueを返す。
検証に失敗した時に作られる`errors`オブジェクトを使うと何で失敗したかが分かる。

```
>> user.errors.full_messages
=> ["Name can't be blank"]
```

当然保存も失敗する。

```
>> user.save
=> false
```

バリデーションを追加したのでテスト

```
$ rails test:models
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
```

同様にメールアドレスのバリデーションも追加
先ずはテストから

```ruby:test/models/user_test.rb
  test "email should be present" do
    @user.email = "     "
    assert_not @user.valid?
  end
```

バリデーション追加

```ruby:app/models/user.rb
validates :email, presence: true
```

テスト

```
$ rails test
10 runs, 20 assertions, 0 failures, 0 errors, 0 skips
```

###長さを検証する
次の検証は長さ
あまりにも長い名前やメールアドレスは登録できないようにしたい。
ということで、長さの上限を設ける。

名前は50文字を上限
メールアドレスは、殆どのデータベースの文字列上限の255字としているので、255文字まで

`name`と`email`の長さに対するテスト

```ruby:test/models/user_test.rb
  test "name should not be too long" do
    @user.name = "a" * 51
    assert_not @user.valid?
  end

  test "email should not be too long" do
    @user.email = "a" * 244 + "@example.com"
    assert_not @user.valid?
  end
```

指定の文字列を作成するには、文字列の掛け算をすればOK

```
>> "a" * 51
=> "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
>> ("a" * 51).length
=> 51
```

テスト追加したので、テスト

```
$ rails test
12 runs, 22 assertions, 2 failures, 0 errors, 0 skips
```

長さの強制するための検証の引数

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name,  presence: true, length: { maximum: 50 }
  validates :email, presence: true, length: { maximum: 255 }
end
```

先ほど追加した存在性の後ろに長さの検証を追加した。
`:maximum`パラメータと一緒に、`:length`で長さの上限を決められる。

バリデーション追加したのでテスト

```
$ rails test
12 runs, 22 assertions, 0 failures, 0 errors, 0 skips
```

###フォーマットを検証する
`name`属性は、空文字でない＆51文字未満であればOK
しかし、`email`属性は、それだけではなく有効なメールアドレスのフォーマットかどうか判定しなければならない。

有効なメールアドレスと無効なメールアドレスのコレクションに対するテストを作る方法がある。
それは、文字列の配列を作れる`%w[]`というものだ。

```
>> %w[foo bar baz]
=> ["foo", "bar", "baz"]
>> addresses = %w[USER@foo.COM THE_US-ER@foo.bar.org first.last@foo.jp]
=> ["USER@foo.COM", "THE_US-ER@foo.bar.org", "first.last@foo.jp"]
>> addresses.each do |address|
?>   puts address
>> end
USER@foo.COM
THE_US-ER@foo.bar.org
first.last@foo.jp
```

まずは、テストを追加
有効なメールフォーマットのテスト

```ruby:test/models/user_test.rb
  test "email validation should accept valid addresses" do
    valid_addresses = %w[user@example.com USER@foo.COM A_US-ER@foo.bar.org
                         first.last@foo.jp alice+bob@baz.cn]
    valid_addresses.each do |valid_address|
      @user.email = valid_address
      assert @user.valid?, "#{valid_address.inspect} should be valid"
    end
  end
```

追加したテストのassertメソッドの第２引数にエラーメッセージがある。
これは、どのメールアドレスが失敗したか特定できるようにしたもの。
文字列を調べるのに、`inspect`メソッドを使用している。
また、`each`メソッドを使って各メールアドレスを順にテストしている。

続いて、**user@example,com**や**user_at_foo.org**等の無効なメールアドレスを使用し、「無効性(Invalidity)」のテストもする。

```ruby:test/models/user_test.rb
  test "email validation should reject invalid addresses" do
    invalid_addresses = %w[user@example,com user_at_foo.org user.name@example.
                           foo@bar_baz.com foo@bar+baz.com]
    invalid_addresses.each do |invalid_address|
      @user.email = invalid_address
      assert_not @user.valid?, "#{invalid_address.inspect} should be invalid"
    end
  end
```

テスト

```
$ rails test
14 runs, 28 assertions, 1 failures, 0 errors, 0 skips
```

メールアドレスのフォーマット検証には次のような`format`というオプションを使う。

```
validates :email, format: { with: /<regular expression>/ }
```

このオプションの引数に正規表現を取る。その正規表現の一つが下のもの

```
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
```

モデルに検証を追加した結果が下のもの

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX }
end
```

因みに大文字で始まるものは、Rubyでは定数としている。
現時点では、`foo@bar..com`の誤りは検出できない。
そのため、下記のように変更すればOK。

```
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
```

バリデーションを追加したのでテスト

```
$ rails test:models
7 runs, 15 assertions, 0 failures, 0 errors, 0 skips
```

###一意性を検証する
一意性とは、他とダブらないということ。
同じものがあってはダメ。

一意性のテストの注意点
・メモリ上にオブジェクトを作るだけではなく、レコードをデータベースに登録する必要がある。
ユーザー１を登録して、ユーザー１と同じメールアドレスを持つユーザー２を登録するという状況を作る。

```ruby:test/models/user_test.rb
  test "email addresses should be unique" do
    duplicate_user = @user.dup
    @user.save
    assert_not duplicate_user.valid?
  end
```

`dup`メソッドは同じ属性を持つデータを複製するためのもの。
このままでは、メールアドレスの大文字と小文字が区別されないため、foo@bar.comはFOO@BAR.COMやFoO@BAr.coMと書いても扱いは同じになる。
なので、テストコードに`upcase`を下記に変更

```ruby:test/models/user_test.rb
  test "email addresses should be unique" do
    duplicate_user = @user.dup
    duplicate_user.email = @user.email.upcase
    @user.save
    assert_not duplicate_user.valid?
  end
```
メールアドレスの一意性の検証をするために、`uniqueness`を追加

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
end
```

しかし、ここではfalseになるため、`:uniqueness`に`:case_sensitve`というオプションを使う。

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
end
```

こうすることで、Railsは`true`と判断する。
しかし、まだ問題がある。
それは、Active Recordはデータベースのレベルまで一意性を保証してない。
現状の検証では、ユーザー登録する前に検証している。なので、トラフィックが多い時や素早く連続２回クリックするとリクエストが２つ連続で送信される。
そうすると、最初のリクエスト１は検証にパスするユーザーを作成し、リクエスト２も同様になる。結果的に、リクエスト１とリクエスト２が保存される。
解決策は、emailカラムにインデックスを追加し一意性が担保されればOK。


<details><summary>もしインデックスがないと？</summary><div>

インデックスがないと、渡されたemailアドレスと、データベースレコードを一人ずつ比較していかなければならない。このことを全表スキャンといって、ユーザーが多ければ多いほどよろしくない。

インデックスを追加すれば、図書館の索引と同じように目印を辿るので簡単に見つけられる。
</div></details>

今回既にマイグレーションが生成されているものに対して、モデル構造に新たにインデックスを追加するので、`migration`ジェネレータを使い直接作成する。

```
$ rails generate migration add_index_to_users_email
```

一意性のマイグレーションが未定義なので、下記のように設定

```ruby:db/migrate/[timestamp]_add_index_to_users_email.rb
class AddIndexToUsersEmail < ActiveRecord::Migration[6.0]
  def change
    add_index :users, :email, unique: true
  end
end
```

`users`テーブルの`email`カラムに`add_index`を使って追加した。
また、`unique: true`で一意性を確保

マイグレートする

```
$ rails db:migrate
```

テストがREDになるため`test/fixtures/users.yml`の中身を消しておく。

Foo@ExAMPle.Comとfoo@example.comを同列の文字列と解釈させるため、データベースに保存する前に文字列をすべて小文字に変換する。
これを実現するために、**コールバック(callback)**メソッドを利用する。

保存する前に実行したいので、`before_save`というコールバックを使う。

```ruby:app/models/user.rb
class User < ApplicationRecord
  before_save { self.email = email.downcase }
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
end
```

`downcase`という文字列メソッドで小文字に変換している。
また、`uniqueness:{case_sensitive: false}`を`uniqueness: true`に戻してOK。理由は、全部小文字にするから。

テストも大文字変換していた箇所を削除した。

なお`self.email = self.email.downcase`ともかけるが、右辺の`self`は省略できるため、`self.email = email.downcase`と書いてもOK。
また、破壊的メソッドを使ったこれもOK
`before_save { email.downcase! }`

""セキュアなパスワードを追加する
パスワードの値をそのままデータベースに保存するのではなく、**ハッシュ化**して保存する。
ハッシュ関数を使って、不可逆的なデータをする処理の事を指す。

ユーザー認証は
①パスワード送信
　↓
②ハッシュ化
　↓
③データベース内のハッシュ化された値と比較
という手順で行う。

生のパスワードは危険なので、、、

###ハッシュ化されたパスワード
Userモデルで、`has_secure_password`メソッドを呼び出せばほぼ完了

・**has_secure_password**の機能
　・`password_digest`という属性が保存できる
　・`password`と`password_confirmation`が使える。また、存在性と値が一致するかのバリデーションも追加される。
　・`authenticate`メソッドが使える。

まだモデル内に`password_digest`という属性がない。従ってUserモデルに`password_digest`のマイグレーション追加のコマンドを実行

```
$ rails generate migration add_password_digest_to_users password_digest:string
```

`users`とすれば`users`テーブルに変更を与えることを伝えられ、`password_digest:string`という引数を与えることで、完全なマイグレーションを生成するための情報をRailsに与えられる。

マイグレーション実行

```
$ rails db:migrate
```

`has_secure_password`を使ってパスワードをハッシュ化するために、最先端のハッシュ関数である`bcrypt`が必要になる。
Gemfileに
`gem 'bcrypt',         '3.1.13'`
と打ち込んで、bundle install実行

Userモデルに`password_digest`属性を追加、`bcrypt`も追加したので準備OK
Userモデル内に
` has_secure_password`
と書く。

ここでテストすると失敗する。
理由は、`has_secure_password`には、仮想的な`password`属性と`password_confirmation`属性に対するバリデーション機能も追加されているから。
テストのsetup内に`password: "foobar", password_confirmation: "foobar"`を追加する。

```ruby:test/models/user_test.rb
  def setup
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end
```

これでテストは成功する。

演習

```
> user = User.new(name: "zippp", email: "zippp@foo.com") 
   (0.4ms)  SELECT sqlite_version(*)
 => #<User id: nil, name: "zippp", email: "zippp@foo.com", created_at: nil, updated_at: nil, password_digest: nil> 
> user.valid?
  User Exists? (0.8ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "zippp@foo.com"], ["LIMIT", 1]]
 => false 
> user.errors.full_messages
 => ["Password can't be blank"] 
```

###パスワードの最小文字数
パスワードの長さが6文字以上の検証をするテストを追加

```ruby:test/models/user_test.rb
  test "password should be present (nonblank)" do
    @user.password = @user.password_confirmation = " " * 6
    assert_not @user.valid?
  end

  test "password should have a minimum length" do
    @user.password = @user.password_confirmation = "a" * 5
    assert_not @user.valid?
  end
```

ここでは多重代入を使っている。

```
@user.password = @user.password_confirmation = "a" * 5
```

パスワードとパスワード確認に対して同時に代入している。

次に、バリデーション追加。`maximum`の反対の`minimum`というオプションを使えばOK

```
validates :password, presence: true, length: { minimum: 6 }
```

因みに、ここのコードにも存在性のバリデーションを入れないと、既にあるユーザーのパスワードを空白6文字で更新できる問題が発生するため存在性のバリデーションがある。

テストは成功した。

演習

```
> user = User.new(name: "zipp", email: "zipp@example.com", password: "foo")
   (0.4ms)  SELECT sqlite_version(*)
 => #<User id: nil, name: "zipp", email: "zipp@example.com", created_at: nil, updated_at: nil, password_digest: [FILTERED]> 
> user.valid?
  User Exists? (0.2ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "zipp@example.com"], ["LIMIT", 1]]
 => false 
> user.errors.full_messages
 => ["Password is too short (minimum is 6 characters)"] 
```

###ユーザーの作成と認証
railsコンソールを使って、開発環境にユーザーを一人新規作成する。

```
$ rails console
>> User.create(name: "Michael Hartl", email: "michael@example.com",
?>             password: "foobar", password_confirmation: "foobar")
```

`password_digest`属性を参照すると、、、

```
 => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2021-05-24 21:42:11", updated_at: "2021-05-24 21:42:11", password_digest: [FILTERED]> 
2.6.3 :007 > user.password_digest
 => "$2a$12$0rJcCo8udpl672xQqpPw9.hAxiuTQPc01N2bWLl5utKJMCkN4T2Oq" 
```

見事にパスワードがハッシュ化されている。
前回`has_secure_password`をUserモデルに追加したので、そのオブジェクト内で`authenticate`メソッドが使えるようになった。
このメソッドは、引数の文字列をハッシュ化した値と、データベース内の`password_digest`カラムの値を比較する。

間違ったパスワードだと、、、false

```
>> user.authenticate("foobaz")
false
```

正しいパスワードだとOK

```
> user.authenticate("foobar")
 => #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2021-05-24 21:42:11", updated_at: "2021-05-24 21:42:11", password_digest: [FILTERED]> 
```

正しいパスワードを入れると、ユーザー情報を返す。
`!!`を付けて`!!user.authenticate("foobar")`とすれば、理論値で返してくれる。

#最後に
あとは、GithubとHerokuにあげればOK

ユーザーモデル、検証、パスワード等追加して何となくWEBアプリケーション`らしく`なってきた。