環境
Rails5.2
Ruby2.6
はじめに
Railsのvalidatesでの数値チェックについて書いてみました。
内容
その1
validatesで数値チェックをする場合、基本な書き方はつぎのようになります。
validates :hoge, numericality: true
この設定は、Railsガイドによると「整数値または浮動小数点数値にマッチする。符号がある場合もマッチする。」と書かれています。つまり、次の入力はすべてOKになります。
0 # 〇
9 # 〇
+9 # 〇
-9 # 〇
0.999 # 〇
9.999 # 〇
+9.999 # 〇
-9.999 # 〇
数値の入力チェックをこれだけで済ませると、あまりにもざっくりしすぎです。ほとんどの場合において、数値の入力チェックは、もっと、他の条件との組み合わせで行うことになります。
その2
整数だけにマッチさせて、浮動小数点数値にはマッチさせたくない場合は、次のようになります。ちなみに±符号もマッチされます。
validates :hoge, numericality: { only_integer: true }
Railsガイドにも書かれていますが、上の書き方は、内部的にはつぎの正規表現で記述した場合と、同じ動きになっています。
validates :hoge, format: {with: /\A[+-]?\d+\z/}
つまり、どっちで記述しても同じだということです。
このようなテスト結果となります。
0 # 〇
9 # 〇
+9 # 〇
-9 # 〇
0.999 # ×
9.999 # ×
+9.999 # ×
-9.999 # ×
テーブルのカラムがInteger型の場合、+符号をつけて更新したとしても、当然ではありますが、テーブルに+符号が付いた状態で更新されるようなことはありません。更新後に再表示をすると、+符号がついていない状態で表示されます。-符号を付けて更新した場合は、当然、-符号がついて更新されます。
その3
符号を付けて更新したくない場合、つまり、符号を付けてsubmitボタンを押すと、入力エラーにしたい場合は、残念ながら、numericalityヘルパーは使えません。
例えば、次のような正規表現を使って、符号が入力できないように自力で制御をかけるしかありません。Railsの標準機能だけでは、こういった、ちょっとした痒い所に手が届かない場合があります。
validates :hoge, format: {with: /\A\d{4}\z/
つぎように、Railsで用意されているヘルパーを使って、入力範囲を1~9999に制限させると、-符号がついた整数は入力できなくなりますが、+100とかは入力ができる状態になります。
+100で更新しても、テーブルのカラムがInteger型であれば問題ないでしょうが、カラムがString型であれば、そのまま+100で更新されることになります。
validates :hoge, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 9999}
numericality: trueを使っても、numericality: { only_integer: true } を使っても、画面のテキスト項目が未入力の状態でsubmitを押すと、共にエラーになります。nilまたは、""で書き込まれてしまうことはありません。
入力項目に「000」で入力してsubmitを押した場合、テーブルのカラムがString型の場合は、当然、そのまま「000」で更新されます。Integer型の場合は「0」が更新されることになります。「000」でsubmitを押しても、再表示した場合は「0」が表示されます。