railsチュートリアル第六章 ユーザーの作成と認証

###ユーザーの作成と認証
以上でUserモデルの基本部分が完了しましたので、今度はユーザー情報表示ページを作成するときに備えて、```データベースに新規ユーザーを1人作成```しましょう。
また、Userモデルに```has_secure_password```を追加した効果についても見ていきましょう。

ただしWebからのユーザー登録はまだできないので、今回はRailsコンソールを使って```ユーザーを手動で作成```することにしましょう。```create```を使いますが、後々実際のユーザーを作成する必要が出てくるので、今回はサンドボックス環境は使いません。
したがって、今回作成したユーザーを保存すると、```データベースに反映```されます。
それでは、まずrails consoleコマンドを実行してセッションを開始し、次に有効な名前・メールアドレス・パスワード・パスワード確認を渡してユーザーを作成してみましょう。

```rb
>> User.create(name: "Michael Hartl", email: "micael@example.com",
?>             password: "foobar", password_confirmation: "foobar")
   (1.6ms)  SELECT sqlite_version(*)
   (0.1ms)  begin transaction
  User Exists? (0.6ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "micael@example.com"], ["LIMIT", 1]]
  User Create (17.2ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at", "password_digest") VALUES (?, ?, ?, ?, ?)  [["name", "Michael Hartl"], ["email", "micael@example.com"], ["created_at", "2021-09-27 13:35:33.010426"], ["updated_at", "2021-09-27 13:35:33.010426"], ["password_digest", "$2a$12$DFJchIS8RiYTgJniH8HFReeYPE.Yq.E9xtfLl6h71xlmpNj5PsimC"]]
   (7.2ms)  commit transaction
=> #<User id: 3, name: "Michael Hartl", email: "micael@example.com", created_at: "2021-09-27 13:35:33", updated_at: "2021-09-27 13:35:33", password_digest: [FILTERED]>
```

うまくデータベースに保存されたかどうかを確認するために、開発環境用のデータベースをDB Browser for SQLiteで開き、usersテーブルの中身を見てみましょう。
もしクラウドIDEを使っている場合は、データベースのファイルをダウンロードして開いてください。
このとき、先ほど定義したUserモデルの属性に対応したカラムがあることにも注目しておいてください。

コンソールに戻って```password_digest```属性を参照してみると、```has_secure_password```の効果を確認できます。

```rb
>> user = User.find_by(email: "micael@example.com")
  User Load (2.7ms)  SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "micael@example.com"], ["LIMIT", 1]]
=> #<User id: 3, name: "Michael Hartl", email: "micael@example.com", created_at: "2021-09-27 13:35:33", updated_at: "2021-09-27 13:35:33", password_digest: [FILTERED]>
>> user.password_digest
=> "$2a$12$DFJchIS8RiYTgJniH8HFReeYPE.Yq.E9xtfLl6h71xlmpNj5PsimC"
```
これは、Userオブジェクトを作成したときに、"foobar"という文字列が```ハッシュ化された結果```です。
```bcrypt```を使って生成されているので、この文字列から元々のパスワードを導出することは、コンピュータを使っても```非現実的```です 。

```has_secure_password```をUserモデルに追加したことで、そのオブジェクト内で```authenticate ```メソッドが使えるようになっています。
このメソッドは、引数に渡された文字列（パスワード）をハッシュ化した値と、データベース内にあるpassword_digestカラムの値を比較します。試しに、先ほど作成したuserオブジェクトに対して間違ったパスワードを与えてみましょう。

```rb
>> user.authenticate("not_the_right_password")
=> false
>> user.authenticate("foobaz")
=> false
```
間違ったパスワードを与えた結果、user.authenticateがfalseを返したことがわかります。
次に、正しいパスワードを与えて、今度はauthenticateがそのユーザーオブジェクトを返すようになります。

```rb
>> user.authenticate("foobar")
=> #<User id: 3, name: "Michael Hartl", email: "micael@example.com", created_at: "2021-09-27 13:35:33", updated_at: "2021-09-27 13:35:33", password_digest: [FILTERED]>
```
第8章では、このauthenticateメソッドを使ってログインする方法を解説します。
なお、authenticateがUserオブジェクトを返すことは重要ではなく、返ってきた値の論理値がtrueであることが重要です。
!!でそのオブジェクトが対応する```論理値オブジェクトに変換```できることを思い出してください。
この性質を利用すると、```user.authenticate```がいい感じに仕事をしてくれるようになります

```rb
>> !!user.authenticate("foobar")
=> true
```

###演習
1.コンソールを一度再起動して（userオブジェクトを消去して）、このセクションで作ったuserオブジェクトを検索してみてください。

```rb
> user = User.find_by(name: "Michael Hartl")                              
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "Michael Hartl"], ["LIMIT", 1]]
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2021-09-23 05:29:52", updated_at: "2021-09-23 05:29:52", password_digest: nil>
```
2.オブジェクトが検索できたら、名前を新しい文字列に置き換え、saveメソッドで更新してみてください。うまくいきませんね...、なぜうまくいかなかったのでしょうか?

```rb
> user.name = "mannbou"
=> "mannbou"

>> user.save
   (0.1ms)  begin transaction
  User Exists? (0.8ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ?  [["email", "michael@example.com"], ["id", 1], ["LIMIT", 1]]
   (0.1ms)  rollback transaction
=> false

>> user
=> #<User id: 1, name: "mannbou", email: "michael@example.com", created_at: "2021-09-
```
3.今度は6.1.5で紹介したテクニックを使って、userの名前を更新してみてください。

```rb
>> user
=> #<User id: 3, name: "Michael Hartl", email: "micael@example.com", created_at: "2021-09-27 13:35:33", updated_at: "2021-09-27 14:39:47", password_digest: [FILTERED]>
>> user.errors.full_messages
=> []
>> user.name = "aa"
=> "aa"
>> user.save
   (0.1ms)  begin transaction
  User Exists? (0.2ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ?  [["email", "micael@example.com"], ["id", 3], ["LIMIT", 1]]
  User Update (0.9ms)  UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["name", "aa"], ["updated_at", "2021-09-27 14:40:24.447792"], ["id", 3]]
   (5.7ms)  commit transaction
=> true
```