3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Rails】3種類のラベルのうち1つは必ず選択(バリデーション)

Posted at

はじめに

現在webアプリ制作に携わらせていただいている中で調べて学んだことをアウトプットしていきたいと思います。
よろしくお願いいたします。

開発環境

Rails 6.0.3
Ruby 3.0.1

参考記事

Active Record バリデーション
Railsで特定の条件下で走るバリデーションを作りたい

どうしたいか

新規質問投稿時に、3種類のタグから当てはまるタグを複数選択できるようになっているが、「投稿時にタグを1つは必ず選択させる」ようなバリデーションを構築したい。

ER図

questionsテーブルにlabelsテーブル、categoriesテーブル 、kindsテーブルがそれぞれ多対多の関係で紐づいています。
Qiita.png

結果

models/question.rb
class Question < ApplicationRecord
  #それぞれのテーブルに中間テーブルを作り多対多の関係にしています
  has_many :labellings, dependent: :destroy
  has_many :labels, through: :labellings
  has_many :category_labellings, dependent: :destroy
  has_many :categories, through: :category_labellings
  has_many :kind_labellings, dependent: :destroy
  has_many :kinds, through: :kind_labellings

  validates :title, presence: true
  # selected_label?メソッドがtrueの場合にバリデーションチェック
  validates :label_ids, presence: { message: "ラベルは必ず1つ選んでください"}, if: :selected_label?

  def selected_label?
    category_ids.empty? && kind_ids.empty?
  end

end

考え方を変えればもう少し早く答えにたどり着いていたかもしれません。
考え方を変え、「3種類のラベルが全て空ではいけない」「2種類のラベルが空の時、1種類のラベルは必須」
この考えにたどり着き、「category_idsとkind_idsが空の時、label_idsが空では保存できない」という実装を思いつきました。
あとは参考記事をもとに、presence: { message: "タグを1種類は選択してください" }の部分でオリジナルのメッセージに変更。
if: :methodif分岐のオプションを使用して、methodメソッドを作り条件分岐を設定ました。
methodではcategory_idskind_idsの値があるか確認し両方値がない場合にtrueを返します。

最後に

見え方や考え方を変えることの大切さを改めて感じました。考え方が固執してしまわないように「逆に考えるんだ!」の言葉を胸に開発を続けます。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?