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

Ruby on Rails: 未来の予約に対するユニーク制約の実装方法

Last updated at Posted at 2024-03-06

背景

Webアプリケーションにおいて、ユーザーが特定の条件下でのみデータを作成できるように制限する必要がある場合がよくあります。特に、予約システムにおいては、一人のユーザーが一つの企業に対して、未来に一つの予約しか持てないようにすることが望ましいケースがあります。

この記事では、Ruby on Railsを使用して、このようなビジネスルールを実装する方法を解説します。

モデルのバリデーション設定

カスタムバリデーションをReservationモデルに追加することで、上記のルールを適用します。

class Reservation < ApplicationRecord
  belongs_to :customer
  belongs_to :company

  validate :unique_future_reservation_per_customer_and_company

  private

  def unique_future_reservation_per_customer_and_company
    return if date.blank? || customer_id.blank? || company_id.blank?

    future_reservations = Reservation.where(customer_id: customer_id, company_id: company_id).where('date >= ?', Date.today)

    future_reservations = future_reservations.where(deleted_at: nil)

    future_reservations = future_reservations.where.not(id: id) unless new_record?

    if future_reservations.exists?
      errors.add(:base, "You can only have one future reservation per company.")
    end
  end
end

解説

このカスタムバリデーションメソッドは、以下のステップで機能します:

  1. 早期リターン: datecustomer_id、またはcompany_idが未設定の場合は、バリデーションをスキップします。
  2. 未来の予約の検索: 同一顧客、同一企業に対して、今日以降の日付で設定された未来の予約を検索します。
  3. 論理削除された予約の除外: deleted_atnilである、つまり論理削除されていない予約のみを対象にします。
  4. 自身の除外: 既存の予約を編集している場合は、自身を検索結果から除外します。
  5. エラーの追加: 上記条件に一致する予約が存在する場合は、エラーメッセージを追加します。

参考記事

ビューとコントローラー

このバリデーションは、モデルレベルで完結しているため、ビューやコントローラーに特別な変更は必要ありません。ただし、ユーザーに対して明確なフィードバックを提供するために、フォームにエラーメッセージを表示するロジックを確実に含めることが重要です。

まとめ

Railsにおけるカスタムバリデーションを利用することで、複雑なビジネスルールも柔軟に実装することができます。今回の事例では、顧客が未来に一つの企業に対して一つの予約しか持てないようにする制約を、簡潔に実現することができました。この方法は、アプリケーションの要件に応じて様々な制約条件に応用可能です。

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