【Rails】エラーメッセージでフォームのレイアウトが崩れる


現象:バリデーションエラー後の画面で入力フォームが崩れる

PFへこのようなお問い合わせフォームを設置しました。

入力する名前とメッセージへそれぞれ次のようにバリデーションを記述

app/models/contact.rb
class Contact < ApplicationRecord
  validates :name, presence: true
  validates :message, presence: true, length: {maximum: 200, minimum: 2}
end

バリデーションが効いているかどうか、いざお試し⋯!!

入力フォームが崩れてしまいました。

原因: 自動挿入される「field_with_errors」

エラー発生後のhtmlを検証ツールで確認すると、inputタグ(名前入力フォーム)とtextareaタグ(メッセージ入力フォーム)を囲むように新たなdivタグが出現していることがわかりました。

出現したdivタグはclass="field_with_errors"とクラスがつけられています。

<div class="field_with_errors">
  入力フォーム
</div>

調べてみると、エラーが発生した際、railsは自動で、エラーメッセージを含むフィールドをfield_with_errorsクラスを持つdivタグで囲んでくれるのだそうです。
それを利用することで、field_with_errorsを指定してCSSを調整することで"エラーが発生しているフォームを赤くして目立たせる"のようなことができるようになるのか!

Railsでは、エラーメッセージを含むフィールドは自動的にfield_with_errorsクラスを持つdivタグで囲まれます。これを利用して、エラーメッセージをもっと目立たせるようにcssルールを定義しても構いません。
Rails をはじめよう / 5.10 バリデーションの追加 – Rails ガイド より

今回はRailsが自動生成してくれたdivタグに囲まれてしまったことでフォームのレイアウトが崩れてしまっていました。

解決策: 2通り 

参考にした記事によると解決方法は2通りあるようです。

  1. 自動挿入されないようにする
  2. 挿入されたクラスのスタイルを編集する

① 自動挿入されないようにする

Railsが自動挿入しないようにする設定はconfig/application.rbに次のように記述することでできるよう。
(わたしは今回こちらの方法で試していないので、これで上手く行かなかったらすみません⋯!)

config/application.rb
module SampleApp
  class Application &lt; Rails::Application
          # 他省略..
    config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag }
  end
end

この方法はRailsが提供してくれている機能を自ら使用できなくするものです。
他のページへ影響する懸念があったため私は2つめの方法を採用しました。

② 追加されたクラスにCSSでスタイルを当てる

新たに追加されたdivタグへレイアウトが崩れないようなCSSを適応させてあげることで解消できました。

.field_with_errors {
  display: contents;
}

私の場合はdisplay: contents;を追加してあげることで治りました。

もし、これで治らなくても検出ツールでいろいろ当ててみてレイアウトが崩れない方法を探してみてください。

学んだこと

「Rails側が自動でやってくれる」
こんなに便利なことはないですね。いたれりつくせり。

しかし、便利な半面、「Railsはどんなときにどんなことをやってくれるのか。」そして、「その裏ではどんなことが起こっているのか。」
をちゃんと知っておかないと予想外のところではまってしまうと感じました。

学習するときは"便利"に甘えず、仕組みまで理解するよう意識したいと思います。

参考にした記事

次の記事により解決までたどり着けました。
https://yukimasablog.com/rails-field-with-errors

公式でfield_with_errorsについて記述があるページです。(ほんの少し)
https://railsguides.jp/getting_started.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%BF%BD%E5%8A%A0

ここまでお読みいただきありがとうございました!