Ich versuche, eine Validierung für einen Zeitraum zu erstellen, sodass ein Zeitraum keinen weiteren Zeitraum enthält.
Das heißt, Periode eins ist von 25 bis 30, und wenn Periode zwei für 20 bis 40 erstellt wird, sollte ein Fehler auftreten
Ich habe versucht, es mit zu validieren
def period_cannot_inbetween_and_other_period
return unless period_overlap(start_week, finish_week).any?
errors.add(:start_week, "-", :finish_week, "cannot be in another Period")
end
und
def period_overlap(start_week, finish_week)
self.class.where(":start_week <= start_week AND :finish_week >= finish_week", start_week, finish_week)
end
Der gesamte Code ist unten
class Period < ApplicationRecord
has_many :days_till_sellables, dependent: :destroy
belongs_to :organization
validates :name, presence: true
validates :start_week, presence: true
validates :finish_week, presence: true
validates :start_week, inclusion: { in: (1..52), message: "%<value>s must be a valid week number" }
validates :finish_week, inclusion: { in: (1..52), message: "%<value>s must be a valid week number" }
validate :start_week_cannot_overlap_period
validate :finish_week_cannot_overlap_period
validate :start_week_cannot_overlap_period_wrap_around
validate :finish_week_cannot_overlap_period_wrap_around
validate :period_cannot_inbetween_and_other_period
protected
def start_week_cannot_overlap_period
return unless regular_overlap(start_week).any?
errors.add(:start_week, "cannot be in another Period")
end
def finish_week_cannot_overlap_period
return unless regular_overlap(finish_week).any?
errors.add(:finish_week, "cannot be in another Period")
end
def start_week_cannot_include_period
return unless regular_overlap(start_week).any?
errors.add(:start_week, "cannot be in another Period")
end
def start_week_cannot_overlap_period_wrap_around
return unless finish_week > start_week && year_end_overlap(start_week).any?
errors.add(:start_week, "cannot be in another Period")
end
def finish_week_cannot_overlap_period_wrap_around
return unless finish_week > start_week && year_end_overlap(finish_week).any?
errors.add(:finish_week, "cannot be in another Period")
end
def period_cannot_inbetween_and_other_period
return unless period_overlap(start_week, finish_week).any?
errors.add(:start_week, "-", :finish_week, "cannot be in another Period")
end
def regular_overlap(week_of_year)
self.class.where("start_week <= :week_of_year AND finish_week >= :week_of_year", week_of_year: week_of_year)
end
def year_end_overlap(week_of_year)
self.class.where("finish_week < start_week AND (start_week <= :week_of_year OR finish_week >= :week_of_year)",
week_of_year: week_of_year)
end
def period_overlap(start_week, finish_week)
self.class.where(":start_week <= start_week AND :finish_week >= finish_week", start_week, finish_week)
end
end
Antworten:
0 für die Antwort № 1Der Zeitraum überschneidet sich also, wenn original_start oder original_end in [start..end] enthalten ist oder wenn [start..end] in [original_start ..original_end] enthalten ist. Im letzten Fall reicht es aus, nur eine Grenze zu überprüfen.
scope :ovelapped_periods, ->(start, finish) { where(start_week: (start..finish)).or(end_week: (start..finish)).or(where(arel_table[:start_week].lt(start)).where(arel_table[:end_week].gt(start))) }
Und ich schlage vor, nur eine Validierung zu belassen, um den Code besser lesbar zu machen
validate :overlapping_period
def overlapping_period
if self.class.ovelapped_periods(start_week, end_week).where.not(id: id).any?
errors.add(:start_week, "Period is overlapped other periods")
end
end