LoginSignup
94
106

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-10-04

はじめに

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.haml
-if model.errors.any? 
  .alert
    %ul
      -model.errors.full_messages.each do |message| 
        %li= message
layouts/error_messages.scss
  .alert {
    color:#262626; 
    background:#FFEBE8;
    text-align: center;
    border:2px solid #990000;
    padding:12px; font-weight:850;
  }

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

products/new.html.haml
 = render 'layouts/error_messages', model: f.object

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

スクリーンショット 2019-10-04 17.31.25.png

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とか)には初めから実装されていることがあります。
ぜひ調べてみてください:santa::santa:

94
106
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
94
106