【发布时间】:2017-02-10 03:35:39
【问题描述】:
情况如下:
我有一个事件模型,我想在视图中添加上一个/下一个按钮以获取下一个事件,但按事件 start 日期时间排序,而不是 ID/created_at。
所以事件是按照开始的顺序创建的,所以我可以比较 ID 或获取下一个最高 ID 或类似的东西。例如。事件 ID 2 在事件 ID 3 之前开始。所以Event.next(3) 应该返回事件 ID 2。
起初我将开始日期时间作为参数传递并获取下一个参数,但是当有 2 个事件具有相同的开始时,这失败了。参数开始日期时间不包括微秒,所以会发生这样的事情:
order("start > ?",current_start).first
会一遍又一遍地返回相同的事件,因为current_start 不包括微秒,所以从技术上讲,当前事件将是> 而不是current_start 0.000000124 秒或类似的东西。
我为所有事情工作的方式是这样的:
module PrevNext
extend ActiveSupport::Concern
module ClassMethods
def next(id)
find_by(id: chron_ids[current_index(id)+1])
end
def prev(id)
find_by(id: chron_ids[current_index(id)-1])
end
def chron_ids
@chron_ids ||= order("#{order_by_attr} ASC").ids
end
def current_index(id)
chron_ids.find_index(id)
end
def order_by_attr
@order_by_attr ||= 'created_at'
end
end
end
型号:
class Event < ActiveRecord::Base
...
include PrevNext
def self.order_by_attr
@order_by_attr ||= "start_datetime"
end
...
end
我知道将所有 ID 放入一个数组中既糟糕又愚蠢*,但我不知道如何
- 按我想要的顺序获取记录列表
- 跳转到该列表中的特定记录(当前事件)
- 然后获取下一条记录
...全部在一个 ActiveRecord 查询中。 (使用带有 PostgreSQL 的 Rails 4)
*此表的记录可能永远不会超过 10k,因此它不是灾难性的糟糕和愚蠢。
我能做到的最好的办法就是按顺序只提取 ID,然后记住它们。
理想情况下,我想通过仅传递事件 ID 而不是开始日期参数来做到这一点,因为它是通过 GET 参数传递的,因此 URL 编码和解码越少越好。
必须有更好的方法来做到这一点。我也在 Reddit 上发布了它,但唯一建议的回复实际上并没有奏效。
感谢任何帮助或见解。谢谢!
【问题讨论】:
标签: ruby-on-rails ruby postgresql datetime