質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.76%

Railsチュートリアル12章 パスワードの再設定をテストする でテンプレートエラーが起こる

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 354

aiandrox

score 47

Railsチュートリアル12.3.3でパスワード再設定のテストを書いたのですが、通りませんでした。
原因を調べてみましたが手詰まりになったので質問させていただきます。
どうかよろしくお願いいたします。

エラーメッセージ

Running via Spring preloader in process 45795
Started with run options --seed 49439

 FAIL["test_password_resets", Minitest::Result, 4.519563999958336]
 test_password_resets#Minitest::Result (4.52s)
        expecting <"password_resets/edit"> but rendering with <[]>
        test/integration/password_reset_test.rb:37:in `block in <class:PasswordResetTest>'

  46/46: [=================] 100% Time: 00:00:04, Time: 00:00:04

Finished in 4.52010s
46 tests, 212 assertions, 1 failures, 0 errors, 0 skips

password_reset_test.rb

require 'test_helper'

class PasswordResetTest < ActionDispatch::IntegrationTest
  def setup
    @user = users(:michael)
    ActionMailer::Base.deliveries.clear
  end

  test "password resets" do
    get new_password_reset_path
    assert_template 'password_resets/new'
    # メールアドレスが無効
    post password_resets_path, params: { password_reset: { email: "" } }
    assert_not flash.empty?
    assert_template 'password_resets/new'
    # メールアドレスが有効
    post password_resets_path, params: { password_reset: { email: @user.email } }
    assert_not_equal @user.reset_digest, @user.reload.reset_digest
    assert_equal 1, ActionMailer::Base.deliveries.size
    assert_not flash.empty?
    assert_redirected_to root_url
    # パスワード再設定フォーム
    user = assigns(:user)
    # メールアドレスが無効
    get edit_password_reset_path(user.reset_token, email: '')
    assert_redirected_to root_url
    # 無効なユーザー
    user.toggle!(:activated)
    get edit_password_reset_path(user.reset_token, email: user.email)
    assert_redirected_to root_url
    user.toggle!(:activated)
    # メールアドレスが有効でトークンが無効
    get edit_password_reset_path('wrong token', email: user.email)
    assert_redirected_to root_url
    # メールアドレスもトークンも有効
    get edit_password_reset_path(user.reset_token, email: user.email)
    assert_template 'password_resets/edit' # ここでエラーが起きます
    assert_select "input[name=email][type=hidden][value=?]", user.email
    # パスワードと確認用パスワードが不一致
    patch password_reset_path(user.reset_token), 
      params: { email: user.email, 
        user: {password: 'foobaz', 
        password_confirmation: 'barquux' } }
    assert_select 'div#error_explanation'
    # パスワードが空
    patch password_reset_path(user.reset_token), 
      params: { email: user.email, 
        user: {password: '', 
        password_confirmation: '' } }
    assert_select 'div#error_explanation'
    # 有効なパスワードと確認用パスワード
    patch password_reset_path(user.reset_token), 
      params: { email: user.email, 
        user: {password: 'foobaz', 
        password_confirmation: 'foobaz' } }
    assert is_logged_in?
    assert_not flash.empty?
    assert_redirected_to user
  end
end

確認したこと

・getの前にdebuggerを入れてuser.reset_tokenを確認したところちゃんと生成されていました。user.emailも"michael@example.com"になっています。
・app/views/password_resets/edit.html.slimは存在します。
・12.3.2の演習まではできているので、開発環境における動作には問題がないと思われます。

ソースコード

routes.rb

Rails.application.routes.draw do
  root 'static_pages#home'
  get '/help', to: 'static_pages#help'
  get '/about', to: 'static_pages#about'
  get '/contact', to: 'static_pages#contact'
  get '/signup', to: 'users#new'
  post '/signup', to: 'users#create'
  get '/login', to: 'sessions#new'
  post '/login', to: 'sessions#create'
  delete 'logout', to: 'sessions#destroy'
  resources :users
  resources :account_activations, only: [:edit]
  resources :password_resets, only: %i[new create edit update]
end

password_resets_controller.rb

class PasswordResetsController < ApplicationController
  before_action :get_user, only: [:edit, :update]
  before_action :valid_user, only: [:edit, :update]
  before_action :check_expiration, only: [:edit, :update]

  def new
  end

  def create
    @user = User.find_by(email: params[:password_reset][:email].downcase)
    if @user
      @user.create_reset_digest
      @user.send_password_reset_email
      flash[:info] = "Email sent with password reset instructions"
      redirect_to root_url
    else
      flash[:danger] = "Email address not found"
      render 'new'
    end
  end

  def edit
  end

  def update
    if params[:user][:password].empty?
      @user.errors.add(:password, :blank)
      render 'edit'
    elsif @user.update_attributes(user_params)
      log_in @user
      flash[:success] = "Password has been reset."
      redirect_to @user
    else
      render 'edit'
    end
  end

  private

    def user_params
      params.require(:user).permit(:password, :password_confirmation)
    end

    def get_user
      @user = User.find_by(email: params[:email])
    end

    def valid_user
      unless (@user && @user.activated? && @user.authenticated?(:reset, params[:id]))
        redirect_to root_url
      end
    end

    def check_expiration
      unless @user.password_reset_expired?
        flash[:danger] = "Password reset has expired."
        redirect_to new_password_reset_url
      end
    end
end

user_mailer_preview.rb

# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
class UserMailerPreview < ActionMailer::Preview

  # Preview this email at http://localhost:3000/rails/mailers/user_mailer/account_activation
  def account_activation
    user = User.first
    user.activation_token = User.new_token
    UserMailer.account_activation(user)
  end

  # Preview this email at http://localhost:3000/rails/mailers/user_mailer/password_reset
  def password_reset
    user = User.first
    user.reset_token = User.new_token
    UserMailer.password_reset(user)
  end
end

動作環境

Rails 5.2.3
ruby 2.5.3
Ruby on Railsチュートリアル 第4版

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

password_resets_controller.rb の check_expiration で、
unless @user.password_reset_expired?
となっていますが、これですと「期限切れでない限り」という意味になって、
続くエラー処理を実行してしまいます。
ここは if とすべきかと。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/12 10:32

    確認して修正したところ、テストが通りました。
    本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Rubyに関する質問
  • Railsチュートリアル12章 パスワードの再設定をテストする でテンプレートエラーが起こる