作ろうとした機能は、タグに応じて投稿フォームの種類を切り替えるやつ。
タグに応じて子モデルが変わり、投稿フォームも変わるようになっています。
しかしこのモデル設計だと、タグの種類によってバリデーションが変えられない問題が生じました。
例えば、子モデルでバリデーションをする場合
class One < ApplicationRecord
belongs_to :post
with_options if: :one? do |one|
one.validates :url, presence: true
end
def one?
tag_id == 1
end
end
このようなエラーがでます。
undefined local variable or method `tag_id'
tag_idが見つからないと怒られてしまいました。
いろいろ調べたところ、上のコードが機能するようにするためには、子モデルが親モデルを継承する必要があるそうです。
しかし、機能追加・機能変更のための継承はよくないとのこと。
参考:https://qiita.com/tonluqclml/items/c0110098722763caa556
そこで、Postモデルを消す形でモデルを修正しました。
Postモデルの子モデルは全て並列の関係になっていたので、モデル設計的にも正しいと思います。
##モデルを書き換えない方法
とはいえ、モデルを書き換えるのは大変なので、緊急的に動作するコードも書いてみました。
結論から言うとカスタムバリデーションを用いると実装できます。
ただ、バリデーションが増えると重複コードが増えて汚くなってしまいます。
class ThreeValidator < ActiveModel::EachValidator
def validate(record)
#先生の紹介のバリデーション
if record.tag_id == 4
unless record.teacher.name.present?
record.errors[:base] << "名前を入力してください"
end
unless record.teacher.job.present?
record.errors[:base] << "職業を入力してください"
end
end
end
end
もっと良い方法とかあれば、教えてください。
##参考文献
https://railsguides.jp/active_record_validations.html
https://qiita.com/tonluqclml/items/c0110098722763caa556
https://qiita.com/kikunantoka/items/61ab74c7f50dedace211