初学者rubyist在这里。我定义了以下范围,我有一种强烈的感觉,我可以用更干燥的方式做到这一点。关于如何以较少重复的方式做到这一点的任何想法?
scope :end_during, ->(new_start_time, new_end_time) do
if (!new_start_time.nil?) && (!new_end_time.nil?)
where('end_time > ? AND end_time < ?', new_start_time, new_end_time)
else
return nil
end
end
scope :start_during, ->(new_start_time, new_end_time) do
if (!new_start_time.nil?) && (!new_end_time.nil?)
where('start_time > ? AND start_time < ?', new_start_time, new_end_time)
else
return nil
end
end
scope :happening_during, ->(new_start_time, new_end_time) do
if (!new_start_time.nil?) && (!new_end_time.nil?)
where('start_time > ? AND end_time < ?', new_start_time, new_end_time)
else
return nil
end
end
scope :enveloping, ->(new_start_time, new_end_time) do
if (!new_start_time.nil?) && (!new_end_time.nil?)
where('start_time < ? AND end_time > ?', new_start_time, new_end_time)
else
return nil
end
end
scope :identical, ->(new_start_time, new_end_time) do
if (!new_start_time.nil?) && (!new_end_time.nil?)
where('start_time = ? AND end_time = ?', new_start_time, new_end_time)
else
return nil
end
end
这是他们的使用方式:
def overlaps
overlapping_bookings = [
subject.bookings.end_during(start_time, end_time),
subject.bookings.start_during(start_time, end_time),
subject.bookings.happening_during(start_time, end_time),
subject.bookings.enveloping(start_time, end_time),
subject.bookings.identical(start_time, end_time)
].flatten
overlapping_bookings.delete self
if overlapping_bookings.any?
errors.add(:base, 'Slot has already been booked')
end
end
答案 0 :(得分:3)
您可以将常见内容分解为另一个范围,然后使用各个范围中的正确参数调用该范围:
scope :time_constraint, ->(c1, f1, c2, f2) do
return nil unless f1 && f2
where "%s ? AND %s ?" % [c1, c2], f1, f2
end
scope :end_during, ->(start_time, end_time) { time_constraint "end_time >", start_time, "end_time <", end_time }
scope :start_during, ->(start_time, end_time) { time_constraint "start_time >", start_time, "start_time <", end_time }
scope :happening_during, ->(start_time, end_time) { time_constraint "start_time >", start_time, "end_time <", end_time }
scope :enveloping, ->(start_time, end_time) { time_constraint "start_time <", start_time, "end_time >", end_time }
scope :enveloping, ->(start_time, end_time) { time_constraint "start_time =", start_time, "end_time =", end_time }
它也不会读得太糟糕。