使用第二个字段订购具有相同日期的记录

时间:2014-07-10 13:26:15

标签: ruby-on-rails activerecord ruby-on-rails-4 scope arel

我有很多画廊的应用程序。每个图库都有一个start_date DateTime字段。

由于遗留原因,所有start_dates的时间都是午夜。

Thu, 10 Jul 2014 00:00:00 UTC +00:00

我需要按照日期订购图库,这样用户就可以使用年龄较大的版本来回移动它们。和'更新'链接。画廊的订购基于start_date:

scope :start_date_ascending, -> { order(start_date: :asc) }
scope :start_date_descending, -> { order(start_date: :desc) }

我的问题是,当有多个具有相同日期的图库时,没有明确的较旧或较新的图库。在这种情况下,我无法预测返回具有相同日期的画廊的顺序,因此在具有相同日期的多个画廊中移动会变得随机且容易出错。

我已设置范围以查找新旧画廊:

scope :newer_than, -> (gallery){ where.not(id:gallery).where('start_date >= :gallery_start_date', gallery_start_date:gallery.start_date) }
scope :older_than, -> (gallery){ where.not(id:gallery).where('start_date < :gallery_start_date', gallery_start_date:gallery.start_date) }

我发现下一个和以前的画廊都是这样的:

def self.next_newer(gallery)
  Gallery.newer_than(gallery).start_date_ascending.limit(1).first
end

def self.next_older(gallery)
  Gallery.older_than(gallery).start_date_descending.limit(1).first
end

所以在我看来,我需要一种次要的方式来订购相同日期的画廊。它的顺序并不重要 - 它可能只是它们的ID。

如何处理这种情况,以便具有相同日期的图库以可预测的固定顺序显示在查询中,以便next_newernext_older通过它们?

2 个答案:

答案 0 :(得分:1)

也许您可以使用第二个条件进行排序,例如name,如果可用,甚至是id

scope :start_date_ascending, -> { order(start_date: :asc, name: :asc) }
scope :start_date_descending, -> { order(start_date: :desc, name: :asc) }

注意start_date_descending范围,保留名称asc可能会很好,所以尽管按日期顺序递减,我们仍按字母顺序排列

对于下一个和上一个图库,如果你可以存储一个数组,你可以得到你订购的id并迭代它们

ids = Gallery.start_date_ascending.pluck :id

答案 1 :(得分:1)

基于@ BengaminSinclaire的建议:

  def self.next_newer(gallery)
    ascending_ids = Gallery.start_date_ascending.pluck :id
    current_index = ascending_ids.index(gallery.id)
    Gallery.find(ascending_ids[current_index+1]) if current_index < ascending_ids.length - 1
  end

  def self.next_older(gallery)
    ascending_ids = Gallery.start_date_ascending.pluck :id
    current_index = ascending_ids.index(gallery.id)
    Gallery.find(ascending_ids[current_index-1]) if current_index > 0
  end