inuinu blog(開発用)

BOT @wagagun の開発ノウハウや、IT向け?の雑記ブログです。

【Ruby on Rails7】バリデーションだけではなくスキーマも連携させる

この記事では、Ruby on Rails7における、スキーマとバリデーションの連携性を解説します。

バリデーションとスキーマの属性は一致させておく

バリデーションだけではなく、実際のテーブルも合わせておくことが望ましいです。

以降は、実際のシステムに近い例示をしつつ、記入例を紹介していきます。

null: falseと, default: ""とpresence: true

Railsではキーや更新日次など主要な項目以外、NULL抑制やデフォルト値は設定されないのですが、多くのDBでは、NULL抑制やデフォルト値を持つことを推奨されます。

以下はマイグレーションの例です。

add_index :customers, :fax_no, unique: true

この例では、デフォルト値が入るので、バリデーションは不要かと思いますが、もし、入力必須を伴う場合は、モデルは以下となります。

validates :fax_no, presence: true

FAXってまだ使うの?
複合機くらいはあるでしょ?的な議論はさておき、入力必須にしている入力フォームは見かけなくなりましたね。

unique: trueとuniqueness: true

Railsの場合はidというプライマリーキーがデフォルトで付加されます。
しかし、顧客コードや商品コード、社員番号、支店コードなど、idの他に基幹システムのマスターコードを持ちたいというニーズはあると思います。

その場合の、マイグレーションはこうなります。
(例は、ユーザーテーブルに社員番号を持ちたいといったケース。)

add_index :users, :shain_cd, unique: true
change_column :users, :shain_cd , :string, limit: 10, null: false, default: ''

モデルはこうなります。

validates :shain_cd, presence: true, uniqueness: true

ユニークキーを作成するとともに、バリデーションでuniqueness: trueを追加します。
これで社員番号の一意性が確保されます。

可能な限り、コード値の場合は有効桁数を設定しましょう(基幹システムと合わせることが望ましい)。
NULLも抑制し、default: ''も付加します。

limit: nとmaximum: n

maximum: nのみ

マイグレーションはこうなります。

change_column :tables, :short_name , :string, limit: 10

モデルはこうなります。

validates :short_name, length: { maximum: 10 }

上記は0文字〜10文字入力可能ですが、入力必須の場合はminimum: 1をつけるか、presence: trueをつけるか、どちらかになります。
(エラーは排他的なので2行になることはありませんが、1文字以上10文字以下というメッセージが、好ましいか悩むところですね。)

minimum: nとmaximum: n

例えば2文字のみ有効としたい場合、マイグレーションはこうなります。

change_column :tables, :category , :string, limit: 2, null: false

モデルはこうなります。

validates :category, length: { minimum: 2, maximum: 2 }

minimum: nとmaximum: nを指定した場合、必ず2文字入力しないといけなくなるので、presence: trueが余計になると思います。
(あっても構いませんが、エラーメッセージが2行表示されて、ちょっとうるさい印象です。)

stringとnumericality: true

こちらは、(桁数制限以外の)マイグレーションは必要ありません。

文字列カラムなのですが、入力値は数値のみというケースがあると思います。
その場合のモデルのバリデーションは以下となります。

validates :flg, numericality: true, length: { minimum: 1, maximum: 1 }

上記例では1桁の数値のみが入力可能です。

integerで行うという方法もありますが、ちょっとめんどくさい気もします。
stringの方が楽そうですね。

qiita.com

stringでnumericalityなケースは大抵の場合、値がすでに決まっているケースが殆どで、ラジオボタンやSELECT/OPTIONのお世話になると思いますので「数値以外エラー」というバリデーションが活躍するケースは少ない気がします。