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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

0回答

1104閲覧

rails tutorial12章で、editからのpassword_resetの検証に失敗してrenderした時のurlが不適切

shumbow

総合スコア35

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2019/05/15 12:09

発生している問題

タイトルの通りなのですが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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問