Railsのバリデーションエラーで、「field_with_errors」によるレイアウト崩れを防ぐ

Ruby / Rails

はじめに

自分が使用していたもののバージョンです。

  • Ruby ver 2.6.3
  • Rails ver 5.2.3
  • bootstrap ver 4.3.1

またバリデーション処理が途中の状態なので、色々気になる箇所があるかもしれませんが、流してください(笑)

現象

Railsのフォームを作成してバリデーションエラーを表示させるときに、入力欄のレイアウトが崩れるという現象が発生しました。

レイアウトが崩れた画像

これは、Railsが自動的にfield_with_errorsクラスを持つdivタグで、labelタグやinputタグを囲むことによって発生したものでした。

Railsでは、エラーメッセージを含むフィールドは自動的にfield_with_errorsクラスを持つdivタグで囲まれます。これを利用して、エラーメッセージをもっと目立たせるようにcssルールを定義しても構いません。

Rails をはじめよう / 5.10 バリデーションの追加 – Rails ガイド より

解決方法

解決方法は、2つあります。

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

この2つのどちらを選ぶかは、エラーメッセージが出るだけで十分であるなら前者で、エラーを目立たせるようなスタイルを当てたければ後者がいいと思います。

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

まず1つ目は、Railsが自動で挿入しないように、設定をファイルに記述すればOKです。

config/application.rbに以下を追加しましょう。

module SampleApp
  class Application < Rails::Application
          # 他省略..
    config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag }
  end
end

上記を追加したら、サーバーを再起動させて再度確認してみると、レイアウトが崩れずにエラーメッセージが出るようになりました。

レイアウトを修正した後のフォームの画像

しかし、これではRailsが提供してくれている機能を自ら使えなくしてしまいます。

そこで、2つ目のやり方です。

挿入されたクラスのスタイルを編集する

結論から言うと、追加されたクラスにCSSでスタイルを当てるだけです。

そもそもこの機能は、バリデーションでエラーになった箇所にクラスを挿入し、そのクラスにエラーを目立たせるスタイルを当てるようにとRailsが用意してくれているものです。

まずはレイアウトの崩れを修正します。

スタイルを記述しているファイルに以下を追記してください。
なお今回は、SASSを使用した例で説明していきます。

.field_with_errors {
  display: contents;
  // もしくは diplay: inline;
}

自分が作成したフォームでは「diplay: contents;」でできましたが、レイアウトによっては、「diplay: inline;」で修正できるかもしれません。

検証ツールを開いて、試してみてください。

次に入力欄の枠が赤色になるようにスタイルを記述します。

Bootstrap3の場合

field_with_errorsクラスに対してBootstrap3の.has-error をextendすることで入力欄を赤枠で表示さることができます。

.field_with_errors {
  display: contents;
  @extend .has-error;
}

Bootstrap4の場合

Bootstrap4の場合は、.has-errorが無くなっているのでextendできません。
代わりにinputタグに対して.is-invalidをextendします。

.field_with_errors {
  display: contents;
  input {
    @extend .is-invalid;
  }
}

上記を追記したらブラウザで確認してみてください。

スタイルを当てて修正したフォームの画像

このようにレイアウトも修正され、バリデーションエラーが発生した入力欄の枠が赤くなったら成功です。

まとめ

Railsのバリデーション機能によって「field_with_errors」クラスのdivタグが挿入されたので、その機能を止めるかレイアウトを修正することで解決できました。

同じ現象に立ち会った人の役に立てればいいなと思います。

Railsの機能が多くて大変です。(笑)

参考記事

おすすめ技術書