干掉范围?

时间:2014-01-01 01:53:59

标签: ruby-on-rails ruby scope

初学者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

1 个答案:

答案 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 }

它也不会读得太糟糕。