takumiblog

新人エンジニアの技術ブログ

編集機能が失敗してしまう原因(バリデーションについて)

はじめに

ユーザー情報の編集機能を実装する際に、つまづいたエラーについてまとめていきたいと思います。

開発環境

MacOS 10.15.7

Rails 6.1.3

今回はdeviceのgemは使用していません。

コード

edit.html.erb

<%= form_tag("/users/#{@user.id}/update",{multipart: true}) do %>  
<h2>アカウント編集</h2>
 <div> 
<label class="form-label">ユーザー名</label> 
<input name="name" class="form-control" > 
</div>
 <div > 
<label class="form-label">メールアドレス</label>
 <input name="email" class="form-control" >
 </div> 
<input type="submit" class="btn btn-primary" value="保存"></input> 
<% end %>

user_controller.rb

 def edit
  @user = User.find_by(id: params[:id]) 
 end
def update
  @user = User.find_by(id: params[:id])
  @user.name = params[:name]
  @user.email = params[:email]
  if @user.save
  flash[:success] ="ユーザー情報を編集できました!
 " redirect_to("/users/#{@user.id}")  
else 
flash.now[:alert] ="編集に誤りがあります" 
render("/user/edit") 
end 
end

結論

はじめに今回のエラーの原因を言ってしまうと、userモデルにvalidates :password, presence: trueと設定していたためでした。

編集画面では、パスワードを変更する欄は作っておらず、どんなに正しい入力をしていてもpasswordのvalidationが引っかかり保存が失敗していたみたいです。

@userの保存がどこで失敗しているか知る必要があったので以下の方法で調査しました。

if @user.save → if @user.save!にしてみる

@user.saveは、正常にセーブできるとtrueを返しますが、失敗するとfalseを返します。なので、成功したか、失敗したかを判断できるような挙動になっています。

@user.saveのとき

一方、@user.save!は、同じく正常にセーブできるとtrueを返しますが、失敗すると例外が発生します。

@user.save!のとき

@user!とすることで上記のように、何で失敗しているのか判断することができます。ここで入力欄のないpasswordのエラーが出ていること気がつき、validationが原因だと気づくことができました。

まとめ

save!を使用することでどこでsaveが失敗しているのか知ることができる。

エラー解決してから気付きましたが、エラーメッセージを表示することでも確認できそうでした…

補足

validatesを制限する方法

validates :password, presence: true, length: {minimum: 6}, on: :creat

on::createとすることで新規登録のみvalidationを働かせることができます。

参考資料

https://qiita.com/ddd555/items/ec58e686607620c9d883