【開発ログ⑬】formに0は入れさせない!!

# 前提について
はじめまして、 プログラミングスクールに通ういりふねと申します。この記事は、スクールの課題である個人アプリの開発の記録を書くことで、自身のアウトプットに利用しています。もし、読んでいただけた方がいましたら、フィードバックをしていただけたら嬉しいです。

開発するのは「有給休暇管理ツール」です。仕様は[過去記事](https://qiita.com/iczo32/items/97ad7d4baa985b3b99ca)をどうぞ。

アプリはデプロイまで行いますが、サービスとして提供するものではありません。あくまでも自学習の一環ですので、ご理解下さい。では本題へどうぞ。

# 今回のアプリのフォームについて
記事にはしていませんが、有休の付与や消化を登録するフォームとそれらを表示するログを作成しました。以下は写真です。

こちらは、フォームです。たい平師匠がよくわからない理由で休もうとしていますが、今回は見逃します。
<img width="233" alt="スクリーンショット 2020-05-15 10.53.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614723/daaf10cb-1ee8-a88b-47a6-f8a0607b58c4.png">

次に有休の付与や消化の履歴を確認するビューです。社員の消化理由を確認したいとか、有休登録を行ったけど間違って登録していないか確認したいなど、入力する人にとって必要であろうと思い設置しています。有休登録の削除もできます。
<img width="867" alt="スクリーンショット 2020-05-17 16.05.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614723/4de0d2c3-53c6-e5e1-05fb-8bc708f561e2.png">

この消化の履歴は、右下に「付与か」「消化か」「付与と消化」が表示されるようにメソッドを設定していますが、ここの条件が今回のテーマに関連します。以下はメソッド部分です。

```ruby:holiday.rb
class Holiday < ApplicationRecord
〜中略〜
  def add_or_delete
    if add_day.nil?
      "#{delete_day}日消化"
    elsif delete_day.nil?
      "#{add_day}日付与"
    else
      "#{add_day}日付与と#{delete_day}日消化"
    end
  end
end
```

add_day(付与日数)やdelete_day(消化日数)がnil（空）かどうかを条件に設定していますが、そこで問題になるのが、「０」という存在です。

# ０もデータでnilとは違う
例えば、有休登録時に付与を0、消化を1と登録すると、履歴には「0日付与と１日消化」と表示されてしまって、非常に不格好になりました。これを避けるためにモデルファイルに定義しているメソッドの条件を「nilまたは0ではない」と変更してもよいのですが、この後、実装する機能にいちいちこの条件を設定するのは面倒。ということでフォーム入力時点で「0」が登録されないようにしたいのです。

# 今回の実施内容
毎度のことながら前置きが長くなりましたが、ここから真の本題です。付与日や消化日のカラムには、nilか1以上の数字しか入らないようにいくつか改良します。具体的には以下のことを行いました。全部必要だったかどうかは、わかりません。

- バリデーション「exclusion」
- フォームの入力制限
- リセットボタンの設置

# バリデーション
0を保存させないと思って真っ先に検索したのが、バリデーションでした。調べてみると「exclusion」という、特定の文字を保存させないバリデーションがありました。

参考にさせていただいた記事[【Rails】完全解説！Railsのバリデーションの使い方をマスターしよう！](https://pikawaka.com/rails/validation)

記事を元に付与日と消化日に「0」という文字が入らないようにバリデーションをかけてみました。

```ruby:holiday.rb
class Holiday < ApplicationRecord
  validates :reason, presence: true
  validates :add_day, exclusion: { in: [0]}
  validates :delete_day, exclusion: { in: [0]}
〜中略〜
end
```

０と入れて試してみましたが、どうやら保存されていないようです。念のため、10日付与なども行いましたが、こちらはちゃんと保存できました。

# フォームの入力制限
しかし、保存されずにindexに戻ってきてしまうため、利用者の方にとっては、なぜ保存されなかったのかが分かりにくくなってしまいます。例えば、付与日を2、消化日を0と打ったが、送信前に間違えに気づき、付与日を0、消化日を2に修正して送信ボタンを押したのに保存されていないなどです。
そこで、フォームそのものにも１以下の数字は入れられないように制限をかけていきます。

```haml:holidays/new.html.haml
〜中略〜
            .field
              .field-label
                = f.label "消化日数"
              .field-input
                = f.number_field :delete_day, max: "50", min: "1"
            .field
              .field-label
                = f.label "付与日数"
              .field-input
                = f.number_field :add_day, max: "50", min: "1"
〜以下省略〜
```

number_fieldに最大50、最小1を追記しました。これによりフォームの上下のボタンでは1~50までしか選択できないようになりました。万が一、手入力で、0を入れて送信しようとしたときには、このフォームの制限によりエラー文が出てくるようになります。
<img width="306" alt="スクリーンショット 2020-05-15 14.11.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614723/d69bf3ad-47cd-423c-10db-1150c2614757.png">

# リセットボタンの設置
これで、0を保存されず、かつフォーム上でも0が送信できないように設定できましたが、念のためフォームのリセットボタンも設置します。わざわざ手入力で0を入れる方は少ないと思ったので、何かの入力ミスで0になってしまったけれど、フォームについている上下ボタンでは、変更できない！！という事態を防ぐためです。

```haml:holidays/new.html.haml
〜中略〜
          .btns
            = f.button "リセット", type: :reset, class: 'btn'
            = f.button "登録", type: :submit, class: 'btn'
```

最初、「f.reset...」とsubmitと同じ要領で記入していたのですが、うまく行かなかったので、再び調べて、下の記事で解決しました。
参考にさせていただいた記事[「Railsでリセットボタンの実装方法」](http://ihatov08.hatenablog.com/entry/2016/04/02/093645)

# ビューの確認
最終的なビューのスクリーンショットを取り忘れていたので、CSSが付与された後の状態になりますが、以下のように完成しました。
<img width="652" alt="スクリーンショット 2020-05-17 16.46.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614723/1dc226c9-ae19-dd35-b8f4-2861f2ec4a65.png">
# 今日の積み上げ
今まで、派手な機能にばかり目を向けていたので、こういった機能も大切であると学びました。あからさまなエラーが出ない分、開発者として細やかな気配りが求められるのではないかと思います。
一方で、こういったバリデーションは、必要であれば、どんどん付けられるのかも知れません。必要十分な量にとどめておかないと作業量が増えすぎるとも感じました。