【问题标题】:Get the Next/Previous record in ActiveRecord on Ruby on Rails在 Ruby on Rails 上的 ActiveRecord 中获取下一条/上一条记录
【发布时间】:2013-11-06 17:25:21
【问题描述】:

我正在尝试通过 ActiveRecord 获取下一条/上一条记录。记录应按照'updated_at'列的顺序检索。

模型的名称是“Youtube”。而作为下面的控制台,这段代码无法获得正确的记录,我猜我的代码的想法似乎很糟糕,因为 updated_at 并不总是唯一的,所以一些记录可能具有相同的时间戳

你如何以正确的方式获得下一个/上一个记录?

控制台如下所述。

[57] pry(main)> Youtube.find(1000)
  Youtube Load (0.5ms)  SELECT "youtubes".* FROM "youtubes" WHERE "youtubes"."id" = $1 ORDER BY updated_at DESC LIMIT 1  [["id", 1000]]
=> #<Youtube id: 1000, author_id: 2, category_label: nil, generated_by: 1, title: "Is Kenya Mall Shooting Over? Were Americans Among A...", video_id: "4T1szQIQcNI", created_at: "2013-09-30 18:31:21", updated_at: "2013-10-27 02:19:56", subtitles: nil>
[58] pry(main)> Youtube.find(1000).next
  Youtube Load (0.6ms)  SELECT "youtubes".* FROM "youtubes" WHERE "youtubes"."id" = $1 ORDER BY updated_at DESC LIMIT 1  [["id", 1000]]
Sun, 27 Oct 2013 02:19:56 UTC +00:00
  Youtube Load (256.6ms)  SELECT "youtubes".* FROM "youtubes" WHERE (updated_at > '2013-10-27 02:19:56.593969') ORDER BY updated_at DESC LIMIT 1
=> #<Youtube id: 67003, author_id: 75, category_label: nil, generated_by: 1, title: "Jewelry Photography : Lenses for Jewelry Photograph...", video_id: "NqA7OZL4tzw", created_at: "2013-10-09 17:18:53", updated_at: "2013-10-28 02:17:33", subtitles: nil>
[59] pry(main)> Youtube.find(1000).previous
  Youtube Load (0.6ms)  SELECT "youtubes".* FROM "youtubes" WHERE "youtubes"."id" = $1 ORDER BY updated_at DESC LIMIT 1  [["id", 1000]]
Sun, 27 Oct 2013 02:19:56 UTC +00:00
  Youtube Load (56.3ms)  SELECT "youtubes".* FROM "youtubes" WHERE (updated_at < '2013-10-27 02:19:56.593969') ORDER BY updated_at DESC LIMIT 1
=> #<Youtube id: 999, author_id: 8, category_label: nil, generated_by: 1, title: "Authors@Google: Richard Moore, Ned Boulting, and Da...", video_id: "4SCzfuJAyJw", created_at: "2013-09-30 18:31:21", updated_at: "2013-10-27 02:19:55", subtitles: nil>

Youtube 有以下 default_scope。虽然这可能会根据某些情况进行更改,但我希望保留此代码以保持现有行为。

  default_scope order('updated_at DESC')

我的 Youtube 模型试用代码如下。

  scope :next, lambda{|updated_at| where("updated_at > ?",
    updated_at).order("updated_at DESC")}
  scope :previous, lambda {|updated_at| where("updated_at < ?",
    updated_at).order("updated_at DESC")}

...

  def next
    self.class.next(updated_at).first
  end 

  def previous                 
    self.class.previous(updated_at).first
  end

【问题讨论】:

标签: ruby-on-rails ruby activerecord ruby-on-rails-3.2 rails-activerecord


【解决方案1】:

我会这样做(可能是更好的方法)...

scope :in_order, lambda{ order("updated_at DESC, id ASC") }

def next
  self.class.in_order.where("updated_at >= ? AND id != ?", updated_at, id).first
end 

def previous
  self.class.in_order.where("updated_at <= ? AND id != ?", updated_at, id).first
end 

【讨论】:

  • 谢谢!此代码显示 Youtube.find(x) 不等于 Youtube.find(x).next.previous。但是这段代码给了我一个提示,我在上面得到了解决和自我回答。
【解决方案2】:

我做了尝试和错误,发现下面是解决方案之一。

代码在这里。

  def next
    self.class.unscoped.where("updated_at <= ? AND id != ?", updated_at, id).order("updated_at DESC").first
  end

  def previous
    self.class.unscoped.where("updated_at >= ? AND id != ?", updated_at, id).order("updated_at ASC").first
  end

测试在这里。

[210] pry(main)> Youtube.find(100)
  Youtube Load (0.8ms)  SELECT "youtubes".* FROM "youtubes" WHERE "youtubes"."id" = $1 ORDER BY updated_at DESC LIMIT 1  [["id", 100]]
=> #<Youtube id: 100, author_id: 5, category_label: nil, generated_by: 1, title: "Woman's Profane Dunkin Donuts Rant Goes Viral", video_id: "-aqN7KdWgQE", created_at: "2013-09-30 18:19:42", updated_at: "2013-10-27 00:47:37", subtitles: nil>
[211] pry(main)> Youtube.find(100).next
  Youtube Load (0.7ms)  SELECT "youtubes".* FROM "youtubes" WHERE "youtubes"."id" = $1 ORDER BY updated_at DESC LIMIT 1  [["id", 100]]
  Youtube Load (95.9ms)  SELECT "youtubes".* FROM "youtubes" WHERE (updated_at <= '2013-10-27 00:47:37.241076' AND id != 100) ORDER BY updated_at DESC LIMIT 1
=> #<Youtube id: 99, author_id: 6, category_label: nil, generated_by: 1, title: "Editing physical locations in Google Maps", video_id: "-amPC4fcY0U", created_at: "2013-09-30 18:19:42", updated_at: "2013-10-27 00:47:36", subtitles: nil>
[212] pry(main)> Youtube.find(100).next.previous
  Youtube Load (0.7ms)  SELECT "youtubes".* FROM "youtubes" WHERE "youtubes"."id" = $1 ORDER BY updated_at DESC LIMIT 1  [["id", 100]]
  Youtube Load (68.8ms)  SELECT "youtubes".* FROM "youtubes" WHERE (updated_at <= '2013-10-27 00:47:37.241076' AND id != 100) ORDER BY updated_at DESC LIMIT 1
  Youtube Load (79.5ms)  SELECT "youtubes".* FROM "youtubes" WHERE (updated_at >= '2013-10-27 00:47:36.162671' AND id != 99) ORDER BY updated_at ASC LIMIT 1
=> #<Youtube id: 100, author_id: 5, category_label: nil, generated_by: 1, title: "Woman's Profane Dunkin Donuts Rant Goes Viral", video_id: "-aqN7KdWgQE", created_at: "2013-09-30 18:19:42", updated_at: "2013-10-27 00:47:37", subtitles: nil>
[213] pry(main)> Youtube.find(100) === Youtube.find(100).next.previous
  Youtube Load (0.8ms)  SELECT "youtubes".* FROM "youtubes" WHERE "youtubes"."id" = $1 ORDER BY updated_at DESC LIMIT 1  [["id", 100]]
  Youtube Load (4.8ms)  SELECT "youtubes".* FROM "youtubes" WHERE "youtubes"."id" = $1 ORDER BY updated_at DESC LIMIT 1  [["id", 100]]
  Youtube Load (99.7ms)  SELECT "youtubes".* FROM "youtubes" WHERE (updated_at <= '2013-10-27 00:47:37.241076' AND id != 100) ORDER BY updated_at DESC LIMIT 1
  Youtube Load (79.6ms)  SELECT "youtubes".* FROM "youtubes" WHERE (updated_at >= '2013-10-27 00:47:36.162671' AND id != 99) ORDER BY updated_at ASC LIMIT 1
=> true

【讨论】:

    【解决方案3】:

    我写了一个 gem 可以自动生成这样的查询,order_query:

    class YouTube < ActiveRecord::Base
      include OrderQuery
      order_query :order_display, [
        [:updated_at, :desc],
        [:id, :desc]
      ]
    end
    
    video = YouTube.find(42)
    pos = video.order_display
    video.next
    video.after
    video.position
    video.prev
    video.before
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-13
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多