はじめに
モデルのバリデーションでうまくいかなかったり、勘違いしていた記述を整理し、学びがあったので書きます。
状況
親モデルとしてproduct
モデル、子モデルとしてproduct_image
モデルがあります。
product
を作成した時は必ず一つ以上のproduct_image
のレコードがあることが条件
以下のようなモデルの記述です。
class Product < ApplicationRecord
has_many :product_images, dependent: :destroy
accepts_nested_attributes_for :product_images, allow_destroy: true
validates_associated :product_images
validates :product_images, presence: true
end
class ProductImage < ApplicationRecord
mount_uploader :image, ImageUploader
belongs_to :product
validates :image, presence: true
end
ここでタイトルの内容のように違いを説明します。
validates_associatedについて
validates_associated :product_images
これでproduct_image
が無い時はバリデーションがかかるものだと思っていたがそれは誤りです。
この表記は「関連付けされている両方のモデルでバリデーションを実行する」
というもの。
私なりの言葉ではアソシエーションされてる先?別?モデルのカラムに対するバリデーションもかけますよ!というもの。
そもそもproduct_image
が空の場合とは意味が違います。
ではどうすればいいのか。
普通にバリデーションかけたいが、product
モデルにはproduct_image
のカラム無いし・・・
と悩んでいました。
答えはすでに記述してあるとおり以下の記述です。
validates :product_images, presence: true
validatesについて
ここでもまだ私には疑問がありました。
validates
の後に記述するのはカラム名では?と。
間違いではないですが、不足している点があります。
その考え方で学びがありました。
わかりやす言えば以下のようにproduct.
のあとに付けれるものはvalidates :
という表記で条件(presence: trueなど)が付けれるということです。
product.name #プロダクトの名前(カラム名)
product.price #プロダクトの金額(カラム名)
product.product_image #プロダクトの画像(アソシエートされてるモデル名)
たしかにアソシエーションかけてるとproduct.
で値が取り出せます!
これの考え方でかなりすっきりしました!