【Ruby on Rails】Rails超入門2❗️凄くて震えるvalidation‼️scaffoldで恐竜登録アプリ作成2


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バリデーション
を参考に実装してみた。

railsアプリのディレクトリ\app\models\dinosor2.rb

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.html.erb

<%= 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 %>

4.検証してみた

ハイブリッド恐竜登録成功

(1)登録済みの恐竜チェック

「同じものを登録したらいけないよ。」

(2)非ハイブリッド恐竜のチェック


「stype1,stype2,sname2,sname1は空であるべきだ。そうは思わないか?」

(3)ハイブリッド恐竜のチェック

「stype1,sname1,stype2,sname2は、入力必須だ。ハイブリッドを手に入れたいだろ?」

(4)非ハイブリッド恐竜のタイプチェック

「恐竜のタイプはリスト内のものと決まっているんだ。これはルールさ」

(5)ハイブリッド恐竜の生成元恐竜タイプチェック

「生成元恐竜のタイプはリスト内のものと決まっているんだ。これはルールさ」

①弾いてる!!条件に合わないって!!!

②しかもなんだか、エラー画面もスタイリッシュ!!

私の大好きな赤というのがいい。Red is god!!

③声の低いイケメンに注意されているみたい←!?

4.まとめ

PHP版恐竜登録ツール
と比較すると、作成工数が大幅に削減されている。
たった一つのコマンドと、少しのvalidationでwebアプリが作れる。
『世界よ。これがRuby on Railsだ』と言ったところだろう。