rails tutorialの9章を参考にログイン機構を作成。
テストについては、rspecを使用しているが、テストが通らない
newHTML
1<div class="row"> 2 <div class="col-md-6 col-md-offset-3"> 3 <%= form_with(url: login_path, scope: :session, local: true) do |f| %> 4 5 <%= f.label :email %> 6 <%= f.email_field :email, class: 'form-control' %> 7 8 <%= f.label :password %> 9 <%= f.password_field :password, class: 'form-control' %> 10 11 <%= f.label :remember_me, class: "checkbox inline" do %> 12 <%= f.check_box :remember_me %> 13 <span>Remember me on this computer</span> 14 <% end %> 15 16 <%= f.submit "Log in", class: "btn btn-primary" %> 17 <% end %> 18 19 <p>New user? <%= link_to "Sign up now!", signup_path %></p> 20 </div> 21</div>
ログインにおいて、emailとpasswordを入力する。
remember_meのチェックボックスがあり、「0」か「1」の情報をsessionに格納する。
SessionsController
1class SessionsController < ApplicationController 2 3 def new; end 4 5 def create 6 @user = User.find_by(email: params[:session][:email].downcase) 7 if @user&.authenticate(params[:session][:password]) 8 log_in @user 9 params[:session][:remember_me] == '1' ? remember(@user) : forget(@user) 10 redirect_to @user 11 else 12 flash.now[:danger] = 'Invalid email / password combination' 13 render 'new' 14 end 15 end 16end 17
params[:session][:remember_me] == '1' ? remember(@user) : forget(@user)
チェックをつけた場合、session[:remember_me]には’1’が格納されている。
'1'の場合、 remember(@user)が発火する。
SessionsHelper
1 def remember(user) 2 user.remember #userにremember_digestにハッシュ化したremember_tokenを格納するメソッド 3 cookies.permanent.signed[:user_id] = user.id 4 cookies.permanent[:remember_token] = user.remember_token 5 end
この処理によりcookieにuser_idとremember_tokenが保存される。
rememberメソッドの中身については、下記コードの通り
Userrb
1class User < ApplicationRecord 2 # 仮想的なremember_token属性を追加 3 attr_accessor :remember_token 4 5 # 渡された文字列のハッシュ値を返す 6 def self.digest(string) 7 cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 8 BCrypt::Engine.cost 9 BCrypt::Password.create(string, cost: cost) 10 end 11 12 # ランダムな文字列でトークンを返す 13 def self.new_token 14 SecureRandom.urlsafe_base64 15 end 16 17 # 永続セッションのためにユーザーをデータベースに記憶する 18 def remember 19 self.remember_token = User.new_token 20 update_attribute(:remember_digest, User.digest(remember_token)) 21 end 22end
以上の前提より、rspecにて
「remember_meが’1’である時、cookieのremember_tokenはnilではない」
というテストを下記の通り実装
TestHelper
1include ApplicationHelper 2 3module TestHelper 4 # ログインする情報を渡すメソッド 5 def log_in_as(user, remember_me: '1') 6 post login_path, params: { session: { 7 email: user.email, 8 password: user.password, 9 remember_me: remember_me 10 } } 11 end 12end
SessionsRequestSpec
1let(:user) { FactoryBot.create(:user) } 2it 'Apply remember_me' do 3 log_in_as(user) 4 expect(response.cookies['remember_token']).not_to eq nil 5end
とした際にテストログは下記画像の通りとなっており、remember_tokenはnilになっている状況らしい
問題の仮説
1私のロジックが間違えている
2タイポの可能性
3rspecがcookieの情報をテストできていない可能性
4rspec内でのメソッドの呼び出すタイミングがずれている(letなど)
何か手がかりでも良いので回答をいただけると助かります。
ほか、参照したいデータがありましたらその都度対応いたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。