0
2

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 5 years have passed since last update.

カスタムバリデーションで他のモデルのカラムを使用する

Posted at

###About
カスタムバリデーションで他のモデルのカラムを使いたい場合の記載方法について記載しています。

###Environment
この記事ではmacbook(unix)にインストールしたruby 2.5.1p57, Rails 5.2.3を使用しています。

#Validationとは
「バリデーション」とは、「検証、実証、認可、妥当性」を意味する英単語
「質的な良し悪し」を判断するのではなく、「システム的な適合不適合」を判断するための言葉

小難しく書きましたが、意図しないデータをDBに登録できない様、バリデーションをかけることが一般的であるそうです。

(参考文献)
https://career-picks.com/business-yougo/validation/

##カスタムバリデーション
通常、バリデーションは以下の様な形式で設定しますが、複雑なバリデーションを設定したい場合、自作のバリデーション(= カスタムバリデーション)を作成します。

通常
class User < ApplicationRecord
  validates :user_id, presence: true
  validates :email, presence: true
end

基本的には、以下の様に定義したメソッド名をvalidate に続けて記載することで、設定可能です。

カスタムバリデーション
class User < ApplicationRecord
  validates :user_id, presence: true
  validates :email, presence: true
  validate :if_user_does_not_have_nickname

  def if_user_does_not_have_nickname
    return if nickname.present?
    errors.add(:nickname, "Nickname is absent")
  end
end

##他のモデルのカラムも組み合わせたい場合
validationを考えていると、他のモデルのカラムを条件として加えたい時があるかと思います。
その様な場合、モデル間でアソシエーションを組むことで他のモデルのカラムを使用することができます。

(例)睡眠時間を記録するアプリ
・日付がデータとして渡されている
・もしユーザの睡眠記録が一つもなければ、睡眠記録の新規作成が可能
・睡眠記録がすでにある場合は、渡されたデータが既存の睡眠記録の最終日付の翌日にマッチしているかどうか調べる
・ミスマッチの場合、渡されたデータを新規登録しない

sleep.ruby
class Sleep < ApplicationRecord
  # アソシエーションの設定。読み込み順の関係で、カスタムバリデーションより必ず上に記載してください。
  belongs_to :user
  validates :slept_time, presence: true
  validates :wakeup_time, presence: true
  # カスタムバリデーションの呼び出し(コントローラでnew, createメソッドの場合のみ)
  validate :dates_cannnot_be_registered_if_there_is_no_yesterdays_date, on: [:new, :create]

  # カスタムバリデーションの作成
  def dates_cannnot_be_registered_if_there_is_no_yesterdays_date
    # もし日付があり、ユーザの睡眠記録がない場合は処理を抜ける(= そのまま新規登録する。)
    return if date.present? && user.sleeps.blank?
    # もし日付がユーザの最新の睡眠記録の日付の翌日でない場合は、データを新規登録しない。
    if date != user.sleeps.last.date.tomorrow
      errors.add(:date, "You can't register that there is no data about before days.")
    end
  end
end

#最後に
いかがでしょうか。アソシエーションを組めていれば、意外と簡単に実装できてしまいます。
私はbelongs toの記述位置がカスタムバリデーションの下になっていたため、エラーと何時間も格闘する羽目になりましたが...。
参考になれば幸いです!

###筆者について

TECH::EXPERTにて4月よりruby, railsを学習している未経験エンジニアです。
記載内容に不備・不足があればご指摘いただけると幸いです。
至らぬ点ばかりですので、改善点がありましたらどんどんご指摘下さい!

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?