私は Hartl rails チュートリアルに取り組んでいます。第 9 章では、編集アクションを現在のユーザーに制限するためのテストを複製しようとしています。
require 'spec_helper'
describe "Authentication" do
subject { page }
....
....
....
describe "as wrong user" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
before { sign_in user, no_capybara: true }
describe "submitting a GET request to the Users#edit action" do
before { get edit_user_path(wrong_user) }
specify { expect(response.body).not_to match(full_title('Edit user')) }
specify { expect(response).to redirect_to(root_url) }
end
describe "submitting a PATCH request to the Users#update action" do
before { patch user_path(wrong_user) }
specify { expect(response).to redirect_to(root_url) }
end
end
end
その後、本の中で説明されているようにコードを実装しましたが、テストはまだ失敗します:
Failures:
1) Authentication as wrong user submitting a PATCH request to the Users#update action
Failure/Error: specify { expect(response).to redirect_to(root_url) }
Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/signin>.
Expected "http://www.example.com/" to be === "http://www.example.com/signin".
# ./spec/requests/authentication_pages_spec.rb:100:in `block (4 levels) in <top (required)>'
テスト内で呼び出される sign_in メソッドにログを追加して調査しました。
def sign_in(user, options={})
Rails.logger.debug "sign_in "+"*"*15
if options[:no_capybara]
# Sign in when not using Capybara.
remember_token = User.new_remember_token
cookies[:remember_token] = remember_token
Rails.logger.debug "Created cookie rt: "+ cookies[:remember_token].to_s
user.update_attribute(:remember_token, User.encrypt(remember_token))
else
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
end
ログ内で create cookie remember_token が空白として報告されます。サインインをsign_in user
(カピバラなしのオプションなしで) に変更すると、ユーザーがサインインし、Cookie が設定されていることがわかりますが、編集アクションにアクセスすると、Cookie が設定されなくなります。
Cookie が破棄されている理由をさらに調査するにはどうすればよいですか?
ありがとう...
詳細については、以下のアプリケーション コードを含めました。
users_controller.rb の内容
class UsersController < ApplicationController
before_action :signed_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
def new
@user = User.new
end
def show
@user = User.find(params[:id])
logger.debug "User show: "+ @user.to_yaml
logger.debug "cookie on user show: "+ cookies[:remember_token].to_yaml
end
def create
@user = User.new(user_params)
if @user.save
sign_in @user
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end
def update
@user = User.find(params[:id])
if @user.update_attributes(user_params)
flash[:success] = "Profile updated"
sign_in @user
redirect_to @user
else
render 'edit'
end
end
def edit
logger.debug "Edit user method"
@user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
def signed_in_user
si = signed_in?
logger.debug "*"*200
logger.debug "signed in user: signed in?: "+si.to_s
redirect_to signin_url, notice: "Please sign in." unless si
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
end
sessions_controller.rb の内容
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email].downcase)
if user && user.authenticate(params[:password])
sign_in user
redirect_to user
else
flash.now[:error] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
sign_out
redirect_to root_url
end
end
sessions_helper.rb の内容
module SessionsHelper
def sign_in(user)
logger.debug "Sessions Helper sign in Method"
remember_token = User.new_remember_token
cookies.permanent[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
self.current_user = user
end
def signed_in?
s_in = !current_user.nil?
logger.debug "signed_in?: "+s_in.to_s
s_in
end
def sign_out
self.current_user = nil
cookies.delete(:remember_token)
end
def current_user=(user)
@current_user = user
end
def current_user
logger.debug "getting current user"
logger.debug "cookie: "+ cookies[:remember_token].to_s
remember_token = User.encrypt(cookies[:remember_token])
logger.debug "rt: "+ remember_token.to_yaml
logger.debug "current_user before: "+ @current_user.to_yaml
@current_user ||= User.find_by(remember_token: remember_token)
logger.debug "current_user after: "+ @current_user.to_yaml
@current_user
end
def current_user?
remember_token = User.encrypt(cookies[:remember_token])
@current_user ||= User.find_by(remember_token: remember_token)
end
def current_user?(user)
user == current_user
end
end