見出し画像

【Rails】 バリデーションエラーメッセージの出し方

はじめに

DBに値を保存する際(ユーザー登録やツイートの登録等)のバリデーションエラー文を表示するやり方について備忘録のために記載しておきます。
参考程度にどうぞ。

バリデーションとは?


バリデーションとはDBに値を保存する際に何か値が抜けていると保存できなくするものです。
簡単に言えばフィルターみたいなものですね。

例えばユーザー登録時にpasswordを入力してもらうとします。passwordが「111」とかだったらセキュリティーが甘くなりますね。
そこでバリデーションを記載してpasswordを8文字以上にしないと登録できないようにすれば、「111」と入力しても弾かれて保存できないようになります。
バリデーションの組み方は無数にあり、やり方を変えれば自分の思い通りに値を保存することができます。

例1)
モデルに下記のように記載すれば空では保存できません。

product.rb
class User < ApplicationRecord
 validates :title, presence: true
end


例2)
モデルに下記のように記載すれば漢字のみ保存できるようになります。

product.rb
class User < ApplicationRecord
 kanji = /\A[一-龥]+\z/
 validates :name, format: { with: kanji }
end

例3)
モデルに下記のように記載すれば"2019-10-04"のような形でのみ保存できるようになります。

product.rb
class User < ApplicationRecord
 year_month_day = /\A\d{4}-\d{2}-\d{2}\z/
 validates :birthday, presence: true, format: { with: year_month_day }
end


バリデーションエラーメッセージの出し方

①商品の保存を行うアクション(ここではcreate)に保存の成功/失敗の条件分岐を記載。
ここで気をつけて欲しいのは失敗時のviewの読み込みはrenderを使用しましょう。
理由は後で解説します。

products_controller.rb
 def create
   @product = Product.new(product_params)
   if @product.save
     redirect_to controller: :products, action: :index
   else
     render "new"
   end
 end 


②エラーメッセージのview作成
htmlのif文をmodel.errors.any? にしておくことでどのモデルのバリデーションにも対応させることができます。

layouts/_error_messages.html.erb

<% if model.errors.any? %>
  <div class = "error">
     <ul>
        <% model.errors.full_messages.each do |message| %>
           <li><%= message %></li>
	    <% end %>
     </ul>
  </div>
<% end %>
layouts/error_messages.scss

alert {
   color:#262626; 
   background:#FFEBE8;
   text-align: center;
   border:2px solid #990000;
   padding:12px; font-weight:850;
 }

③エラーメッセージの表示
あとはエラーメッセージを表示させたいところに以下のコードを記載するだけです。

products/new.html.erb

<%= render 'layouts/error_messages', model: f.object %>

完成です。
こんな感じになります。めちゃめちゃ簡単です。

画像1

redirect_toとrenderの違い

先ほど、失敗時のviewの読み込みはrenderを使用すると記載しましたが、そこについて軽く触れます。
redirect_toとrenderはルーティングを通るか通らないかという違いがあります。
redirect_to…ルーティングを通り、新たにviewページを呼び出す。
render…ルーティングを通らず、viewページに飛ぶ。
正式にはもっと違いがありますが、とりあえずこの認識でOKです。

なので失敗時のviewの読み込み(以下の部分)をredirect_toにすると、
新しいビューページが呼ばれてしまうため、ページに書いたif文が反応しません。

products_controller.rb

 def create
      ~省略~
   else
     render "new"
   end
 end


おわりに


特定のgem(例えばdeviseとか)には初めから実装されていることがあります。
ぜひ調べてみてください

この記事が気に入ったらサポートをしてみませんか?