ぞえの技術めも

Ruby on Rails勉強中

【49日目】【1日20分のRailsチュートリアル】【第6章】Userモデルへのセキュアなパスワードとパスワードの最小文字数を設定する

Ruby on Railsチュートリアル(第3版)

今日は「6.3.2 ユーザーがセキュアなパスワードを持っている」から。

6.3.2 ユーザーがセキュアなパスワードを持っている

Userモデルにpassword_digest属性を追加し、Gemfileにbcryptを追加したことで、ようやくUserモデル内でhas_secure_passwordが使えるようになりました (リスト6.34)。

ということでUserモデルでhas_secure_passwordを使う。

app/models/user.rb

class User < ActiveRecord::Base
  :
  has_secure_password
end

テスト実行。

$ bundle exec rake test
 :
 FAIL["test_email_validation_should_accept_valid_addresses", UserTest, 2016-08-09 12:46:01 +0000]
 test_email_validation_should_accept_valid_addresses#UserTest (1470746761.13s)
        "user@example.com" should be valid
        test/models/user_test.rb:38:in `block (2 levels) in <class:UserTest>'
        test/models/user_test.rb:36:in `each'
        test/models/user_test.rb:36:in `block in <class:UserTest>'

 FAIL["test_should_be_valid", UserTest, 2016-08-09 12:46:01 +0000]
 test_should_be_valid#UserTest (1470746761.14s)
        Expected false to be truthy.
        test/models/user_test.rb:10:in `block in <class:UserTest>'

16 tests, 31 assertions, 2 failures, 0 errors, 0 skips

Userが有効じゃないよ、的なエラー出る。

テストが失敗する理由は、6.3.1で触れたようにhas_secure_passwordには、仮想的なpassword属性とpassword_confirmation属性に対してバリデーションをする機能も(強制的に)追加されているからです。
しかしリスト6.25のテストでは、@user 変数にこのような値がセットされておりません。

password属性とpassword_confirmation属性に何も設定してないからUserとしては無効、って感じかな。

というわけでテスト用Userのpassword属性とpassword_confirmation属性を設定。

test/models/user_test.rb

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

テスト通りました。

$ bundle exec rake test
16 tests, 35 assertions, 0 failures, 0 errors, 0 skips

6.3.3 パスワードの最小文字数

パスワードの長さが6文字以上であることを検証するテストを、以下のリスト6.38に示します。

最大文字数はいいのかな…?って思ったけどまぁいいか。。
少ない文字数のパスワードは禁止してセキュリティを上げるのが目的なので。

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

テストコード追加しただけなのでテスト失敗。

$ bundle exec rake test
18 tests, 37 assertions, 2 failures, 0 errors, 0 skips

Userモデルに最小文字数のバリデーションと存在性のバリデーションを追加。

(has_secure_passwordメソッドは存在性のバリデーションもしてくれるのですが、これは新しくレコードが追加されたときだけに適用されます。したがって、たとえばユーザーが " " (6文字分の空白スペース) といった文字列をパスワード欄に入力して更新しようとすると、バリデーションが適用されずに更新されてしまう問題が発生してしまいます。)

へ~。

app/models/user.rb

class User < ActiveRecord::Base
  :
  validates :password, presence: true, length: { minimum: 6 }
end

テスト通りました。

$ bundle exec rake test
18 tests, 37 assertions, 0 failures, 0 errors, 0 skips

"セキュア"なパスワードを意識することなくUserモデルへのパスワード追加ができましたね。
中身全く分からない。まぁいいか。便利です。

今日の作業時間は【19分】

次は「6.3.4 ユーザーの作成と認証」から。