/ / Das Überprüfen eines Ganzzahlbereichs ist nicht in einem anderen Ganzzahlbereich enthalten - Ruby-on-Rails, Activerecord

Das Überprüfen eines Ganzzahlbereichs ist in einem anderen Ganzzahlbereich nicht enthalten - Ruby-on-Rails, Activerecord

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 № 1

Der 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