【问题标题】:DRYing out scope?干燥范围?
【发布时间】:2014-01-01 01:53:59
【问题描述】:

这里是红宝石初学者。我定义了以下范围,我有一种强烈的感觉,我可以用一种更干燥的方式来做到这一点。关于如何以较少重复的方式执行此操作的任何想法?

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

【问题讨论】:

  • 我添加了一个 Rails 标记,因为您询问 Rails 和 Ruby 一样多
  • 只是为了确认一下,start_duringhappening_during 应该是相同的吗?
  • 看起来甚至envelopingstart_duringhappening_during 相同。不确定这是否是一个说明性示例?也许scope_chaining 是您要找的?
  • 列名和比较不同。我也被它抓住了。
  • 它们是不同的。有点,但不一样。这就是为什么我不知道如何以更简单的方式制作它。

标签: ruby-on-rails ruby scope


【解决方案1】:

您可以将常见的东西分解到另一个作用域中,然后使用各个作用域中的正确参数调用它:

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 }

它读起来也不算太糟糕。

【讨论】:

    猜你喜欢
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多