LoginSignup
1
1

More than 1 year has passed since last update.

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

Posted at

ユーザーの作成と認証

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

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

>> 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の効果を確認できます。

>> 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オブジェクトに対して間違ったパスワードを与えてみましょう。

>> user.authenticate("not_the_right_password")
=> false
>> user.authenticate("foobaz")
=> false

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

>> 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がいい感じに仕事をしてくれるようになります

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

演習

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

> 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メソッドで更新してみてください。うまくいきませんね...、なぜうまくいかなかったのでしょうか?

> 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の名前を更新してみてください。

>> 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
1
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
1
1