rails tutorial 第9章


はじめに

独学でrails tutorialを進めていく過程を投稿していきます。

進めていく上でわからなかった単語、詰まったエラーなどに触れています。

個人の学習のアウトプットなので間違いなどあればご指摘ください。

初めての投稿なので読みにくいところも多々あるかと思いますがご容赦ください。

第9章 発展的なログイン機構

9.1.1 記憶トークンと暗号化

attr_accessorの復習

参考
https://qiita.com/Hassan/items/0e034a1d42b2335936e6
.remember_tokenが使えるようになります(remember_token属性が扱えるようになった)

def remember
  self.remember_token = User.new_token
  update_attribute(:remember_digest, User.digest(remember_token))
end

最後の(remember_token)はself.が省略されています。

9.1.2 ログイン状態の保持

BCrypt::Password.new(remember_digest) == remember_token

このコードをじっくり調べてみると、実に奇妙なつくりになっています。bcryptで暗号化されたパスワードを、トークンと直接比較しています。(rails tutorial 9章より引用)

ふむふむ、確かに、、、

==で比較する際にダイジェストを復号化しているのでしょうか。
しかし、bcryptのハッシュは復号化できないはずなので、復号化しているはずはありません。(rails tutorial 9章より引用)

なるほど、、では何が起こっているのでしょう?

BCrypt::Password.new(remember_digest).is_password?(remember_token)

どうやら上の2つのコードは同じ意味のようです。
また、is_password?メソッドでオブジェクトと渡された引数の検証をし、一致している場合trueを返しているようです。

9.3.2 [Remember me]をテストする

また、リスト 9.24で定義したlog_in_asヘルパーメソッドでは、session[:user_id]と定義してしまっています。このままでは、current_userメソッドが抱えている複雑な分岐処理を統合テストでチェックすることが非常に困難です。(rails tutorial 9章より引用)

ん?なぜでしょう?
A.
統合テストではsessionメソッドが扱えないから

test/test_helper.rb
def log_in_as(user)
    session[:user_id] = user.id #使えない
end

test/helpers/sessions_helper_test.rb
test "current_user returns right user when session is nil" do
    assert_equal @user, current_user
    assert is_logged_in?
end

このcurrent_userとは
current_userメソッドが実行された上でモデルオブジェクトとなっているようです。多分、、、

つまり
log_in user
なども行われており、sessionメソッドも実行されているのだと思います、、、

app/helpers/sessions_helper.rb
def current_user
  if user_id = session[:user_id] #false
    @current_user ||= User.find_by(id: user_id)
  elsif user_id = cookies.signed[:user_id] #true
    user = User.find_by(id: user_id)
    if user && user.authenticated?(cookies[:remember_token])
      log_in user #ログインされる
      @current_user = user
    end
  end
end

current_userメソッドは戻り値にモデルのインスタンスを返すモデルオブジェクト。


test/helpers/sessions_helper_test.rb
test "current_user returns nil when remember digest is wrong" do
    @user.update_attribute(:remember_digest,User.digest(User.new_token))
    assert_nil current_user
end
@user.update_attribute(:remember_digest, User.digest(User.new_token))

remember_digestを新しいものに更新。

assert_nil current_user

app/helpers/sessions_helper.rb
def current_user
  if user_id = session[:user_id]
    @current_user ||= User.find_by(id: user_id)
  elsif user_id = cookies.signed[:user_id]
    user = User.find_by(id: user_id)
    if user && user.authenticated?(cookies[:remember_token]) #falseとなりcurrent_userはnilとなる
      log_in user
      @current_user = user
    end
  end
end
if user && user.authenticated?(cookies[:remember_token])

こちらの検証に置いてcurrent_userがnilとなるか確かめています。

終わりに

こちらの章ではエラーで躓くことも少なく、内容もよく理解出来ました。