発生している問題
タイトルの通りなのですがrails tutorial 12章 ここのあたりです で、password再設定を実装しているのですが、formで不正な値を入れてpatch password_reset_path(reset_token)をすると、バリデーションでひっかかってeditをrenderするというありがちなやつだと思うんですけど、通常のeditへのurlは(password再設定メールから飛んできたリンク)、http://http://localhost:3000/password_resets/Wg5lJNFsK84NeWVNcdIovQ/edit/?email=xxx%40yyyyyy
(:idは@user.reset_token)にがなるのですがrenderで表示されたeditのurlは
http://http://localhost:3000/password_resets/Wg5lJNFsK84NeWVNcdIovQ
と、edit以下が消えてしまっています。そのため、この状態でブラウザを更新するとno routes match エラーが発生します。
No route matches [GET] "/password_resets/Wg5lJNFsK84NeWVNcdIovQ" root_path GET / main_pages#top help_path GET /help(.:format) main_pages#help signup_path GET /signup(.:format) users#new POST /signup(.:format) users#create login_path GET /login(.:format) sessions#new POST /login(.:format) sessions#create logout_path DELETE /logout(.:format) sessions#destroy users_path GET /users(.:format) users#index POST /users(.:format) users#create new_user_path GET /users/new(.:format) users#new edit_user_path GET /users/:id/edit(.:format) users#edit user_path GET /users/:id(.:format) users#show PATCH /users/:id(.:format) users#update PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy edit_account_activation_path GET /account_activations/:id/edit(.:format) account_activations#edit password_resets_path POST /password_resets(.:format) password_resets#create new_password_reset_path GET /password_resets/new(.:format) password_resets#new edit_password_reset_path GET /password_resets/:id/edit(.:format) password_resets#edit password_reset_path PATCH /password_resets/:id(.:format) password_resets#update PUT /password_resets/:id(.:format) password_resets#update
考えられる原因としては、railstutorialはたぶんraisl5.1.2なのにたいして自分は5.1.7なのでそれか、form作成にform_forではなくform_withを使っているからなのかもしれませが、そもそもtutorialの方でも起きているバグなのかもわかりません。(git cloneして調べようとしたが、bundlerのバージョンの関係でbundle install失敗しました)
実際はユーザーが戻るボタンで戻れば問題なく使えるのでなおさなくてもよいかもしれないので、この程度のエラーは放置するべきなのでしょうか?でも解決方法がわかる方はぜひ教えていただきたいです。
試したこと、惜しかったところ
renderじゃなくてredirect_to(password_reset_path(params[:id], @user.email))
として明示的にフルパスを示せばいいじゃないかとおもってやってみたらうまく機能したのですが、バリデーション失敗のエラーメッセージが消えてしまうので、結局使っていません。(また、余計なリクエストも増えてしまうといやなので)
以下関係するファイルです。
views/password_resets/edit.html.erb
erb
1<% provide(:title, 'パスワード再設定') %> 2<h1 class="heading">パスワード再設定</h1> 3<p>新しいパスワードを設定してください</p> 4 <%= form_with(model: @user, url: password_reset_path(params[:id]), local: true) do |form| %> 5 <div class="row"> 6 <div class="col-10 offset-md-1"> 7 <%= render 'shared/error_messages'%> 8 </div> 9 </div> 10 11 <div class="row"> 12 <div class="col-10 col-md-8 mx-auto"> 13 <%= hidden_field_tag :email, @user.email %> 14 <%= form.label :password, "パスワード" %><small class="text-muted"> 半角英数字で6以上20文字以下で設定</small> 15 <%= form.password_field :password, class: 'form-control' %> 16 </div> 17 </div> 18 <div class="row"> 19 <div class="col-10 col-md-8 mx-auto"> 20 <%= form.label :password_confirmation, "パスワード確認" %><small class="text-muted"> 確認のためもう一度ご入力ください</small> 21 <%= form.password_field :password_confirmation, class: 'form-control' %> 22 </div> 23 </div> 24 <div class="row mt-3"> 25 <div class="col-3 mx-auto"> 26 <%= form.submit "更新する", class: "btn btn-primary submit" %> 27 </div> 28 </div > 29 <% end %> 30</div>
controller/password_resets_controller.rb
erb
1class PasswordResetsController < ApplicationController 2 before_action :get_user, only: [:edit, :update] 3 before_action :valid_user, only: [:edit, :update] 4 before_action :check_expiration, only: [:edit, :update] 5 6 def new 7 end 8 9 def create 10 @user = User.find_by(email: params[:password_reset][:email].downcase) 11 if @user 12 @user.create_reset_digest 13 @user.send_password_reset_email 14 flash[:success] = "再設定用リンクを送りました。ご確認ください。" 15 redirect_to root_url 16 else 17 flash[:danger] = "このメールアドレスは登録されていません" 18 render 'new' 19 end 20 end 21 22 def edit 23 end 24 25 def update 26 if params[:user][:password].empty? 27 @user.errors.add(:password, :blank) 28 render 'edit' 29 elsif @user.update_attributes(user_params) 30 log_in @user 31 @user.update_attribute(:reset_digest, nil) 32 flash[:success] = "パスワード変更されました" 33 redirect_to @user 34 else 35 render 'edit' 36 end 37 end 38 39 private 40 41 def user_params 42 params.require(:user).permit(:password, :password_confirmation) 43 end 44 45 def get_user 46 @user = User.find_by(email: params[:email]) 47 end 48 49 # 正しいユーザーかどうか確認する 50 def valid_user 51 unless (@user && @user.activated? && 52 @user.authenticated?(:reset, params[:id])) 53 redirect_to root_url 54 end 55 end 56 57 def check_expiration 58 if @user.password_reset_expired? 59 flash[:danger] = "有効期限(2時間)が切れています。もう一度やり直してください。" 60 redirect_to new_password_reset_url 61 end 62 end 63end
あなたの回答
tips
プレビュー