###1.validationとは
コマンド一つでcrudアプリが作れる時点で十分凄いのだが、
この恐竜登録には、少し問題がある。
それは、何回でも同じ名前の恐竜が登録できてしまったり、
全て空のデータが登録できてしまったりする事だ。
その理由として、モデル生成の時、rails側で用意したこちらIDという項目がモデルで定義したテーブルに付与され、さらにこのIDがキーになっているためだと思われる。
上記の事態を避けるために、データ登録時に制約を追加しなくてはならない。
例えば以下のルールを与えてみる。
- 生成恐竜名(dname0)と生成タイプ(dtype0)は入力必須
- hflgにチェックを入れた時(ハイブリッド型)は、生成元恐竜1(sname1)、生成元恐竜2(sname2)、生成元タイプ1(stype1)、生成元タイプ2(stype2)は必須
- hflgにチェックを入れない時(非ハイブリッド型)は、生成元恐竜1(sname1)、生成元恐竜2(sname2)、生成元タイプ1(stype1)、生成元タイプ2(stype2)は空にする
- 登録済み生成恐竜名と生成タイプを入力した時は登録しない。
- 生成恐竜タイプは、normal,rare,epic,regend,uniqueとする。
- 生成元恐竜タイプ1と生成元恐竜タイプ2は、normal,rare,epic,regendとする。
この__モデルで定義したテーブルに登録するために入力データに設けるルールをvalidationというらしい。__
###2.validation実装
[ActiveRecordバリデーション] (https://railsguides.jp/active_record_validations.html#バリデーションの概要)
を参考に実装してみた。
class Dinosor2 < ApplicationRecord
# dname0は入力必須。
validates :dname0, presence: true
# dtype0はnormal,rare,epic,regendの何れかを指定
validates :dtype0, inclusion: { in: %w(normal rare epic regend unique) }
# dname0とdtype0の組み合わせでユニーク
validates :dname0, uniqueness: { scope: :dtype0 }
# hflgにチェックが入っているとき、stype1はnormal,rare,epic,regendの何れかを指定
validates :stype1, inclusion: { in: %w(normal rare epic regend) } , if: '!hflg.blank?'
# hflgにチェックが入っているとき、sname1は入力必須
validates :sname1, presence: { if: '!hflg.blank?' }
# hflgにチェックが入っているとき、stype2はnormal,rare,epic,regendの何れかを指定
validates :stype2, inclusion: { in: %w(normal rare epic regend) } , if: '!hflg.blank?'
# hflgにチェックが入っているとき、sname2は入力必須
validates :sname2, presence: { if: '!hflg.blank?' }
# hflgにチェックが入っていないとき、stype1,sname1,stype2,sname2は空にする。
validates :stype1,:sname1,:stype2,:sname2, absence: { if: 'hflg.blank?' }
end
###3.viewの変更
下記のviewを修正したのはdtype0,stype1,stype2の入力欄の前に、
タイプ欄を表示するようにした。
エラーメッセージを見るとわかるのだがリスト内の定義が見えないと入力が難しいためだ。
<%= form_with(model: dinosor2, local: true) do |form| %>
<% if dinosor2.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(dinosor2.errors.count, "error") %> prohibited this dinosor2 from being saved:</h2>
<ul>
<% dinosor2.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<% d_type = "(normal,rare,epic,regend,unique)" %>
<% s_type = "(normal,rare,epic,regend)" %>
<div class="field">
<%= form.label :dname0 %>
<%= form.text_field :dname0, id: :dinosor2_dname0 %>
</div>
<div class="field">
<%= form.label :dtype0 %>
<%= d_type %><br>
<%= form.text_field :dtype0, id: :dinosor2_dtype0 %>
</div>
<div class="field">
<%= form.label :sname1 %>
<%= form.text_field :sname1, id: :dinosor2_sname1 %>
</div>
<div class="field">
<%= form.label :stype1 %>
<%= s_type %><br>
<%= form.text_field :stype1, id: :dinosor2_stype1 %>
</div>
<div class="field">
<%= form.label :sname2 %>
<%= form.text_field :sname2, id: :dinosor2_sname2 %>
</div>
<div class="field">
<%= form.label :stype2 %>
<%= s_type %><br>
<%= form.text_field :stype2, id: :dinosor2_stype2 %>
</div>
<div class="field">
<%= form.label :hflg %>
<%= form.check_box :hflg, id: :dinosor2_hflg %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
「同じものを登録したらいけないよ。」
(2)非ハイブリッド恐竜のチェック
「stype1,stype2,sname2,sname1は空であるべきだ。そうは思わないか?」
(3)ハイブリッド恐竜のチェック
「stype1,sname1,stype2,sname2は、入力必須だ。ハイブリッドを手に入れたいだろ?」
(4)非ハイブリッド恐竜のタイプチェック
「恐竜のタイプはリスト内のものと決まっているんだ。これはルールさ」
(5)ハイブリッド恐竜の生成元恐竜タイプチェック
「生成元恐竜のタイプはリスト内のものと決まっているんだ。これはルールさ」
####①弾いてる!!条件に合わないって!!!
####②しかもなんだか、エラー画面もスタイリッシュ!!
私の大好きな赤というのがいい。Red is god!!
####③声の低いイケメンに注意されているみたい←!?
###4.まとめ
[PHP版恐竜登録ツール]
(https://qiita.com/knowledge87sun/items/aea1c603cab586b7bcf5)
と比較すると、作成工数が大幅に削減されている。
たった一つのコマンドと、少しのvalidationでwebアプリが作れる。
__『世界よ。これがRuby on Railsだ』__と言ったところだろう。