如何在Ruby on Rails中获取某些记录?

时间:2011-02-25 15:00:45

标签: ruby-on-rails ruby activerecord

我有一个名为note的模型。我目前得到这样的笔记:

current_user.notes.order('date DESC, created_at DESC').limit(10).reverse!

我现在需要做以下事情: 取一个note_id参数,然后返回10个音符:参数中的一个和第一个附近的9个其他音符。

理想情况下,根据上面第一行中的顺序,其他9个音符将在主音符之前分配为5,在之后4之后(或在之后的4之前和之后为5)。

示例:

note note note note primary_note note note note note note

有时候这是不可能的。例如,如果primary_note是用户的第二个音符,它应该返回:

note primary_note note note note note note note note note

或者如果它是最新的音符,并且用户总共只有3个音符,则应该返回:

note note primary_note

我该怎么做?我正在使用ruby 1.9.2& Rails 3.0.1

2 个答案:

答案 0 :(得分:4)

我认为没有办法通过单一查询获得这些笔记 - 您至少需要两个。从我对SQL(对某种程度有限)的理解,你必须做到的唯一方法是:

  • 获取“primary_note
  • 之前的4个音符
  • 在“primary_note
  • 之后”获取4个音符
  • 加入两套

类似的东西(警告:未经测试的代码)

class Note < ActiveRecord::Base
  # on rails 3 I prefer class methods to named scopes.
  # they are equally "chainable" and have simpler syntax
  def self.notes_before(date, limit=4)
    self.where(['date >= ?', date]).order("date DESC, created_at DESC").limit(limit)
  end

  def self.notes_after(date, limit=4)
    self.where(['date <= ?', date]).order("created_at ASC, date ASC").limit(limit)
  end

  # Instance method
  def notes_around(limit=4)
    (Note.notes_before(self.date, limit) << self) + Note.notes_after(self.date, limit)
  end
end

用法:

n = Note.new(:date => Date.yesterday)
n.notes_around # returns the 9 notes around n, plus n
n.notes_around(40) # returns 81 notes

# in addition:
Note.notes_before(Date.today, 40) # last 40 notes
Note.notes_after(Date.today, 10).where(:color => 'blue') # chainable

但我想不出一个“可连接的类方法”。也许我不太了解SQL。

  

理想情况下,其他9个笔记将是   在主要说明之前分配为5   和之后的4(或之前的4和之后的5),   基于第一个排序   上面的行

我不明白你如何确定在这种情况下你需要“4”或“5”。所以我假设你知道这一点。

答案 1 :(得分:2)

您可以在查询中使用range condition

class Note
  scope :around_note_id, lambda { |id| where(:id => range_for_search(id) }

  def self.range_for_search(id)
    # your logic here, i.e.
    # (id-1)..(id+1)
  end
end

> Note.around_note_id(3)