Rails查询:根据最新的子记录获取所有父记录

时间:2015-11-08 21:49:03

标签: ruby-on-rails activerecord

订单AutoSort() order_events。

has_many是订单状态的记录,例如order_eventpending_approval等。

通过创建confirmed跟踪订单的更改。

我通常通过执行以下操作来获取订单的当前状态:order_events

我想查询以获取具有给定当前状态的所有订单,例如,当前状态为order.order_events.last.try(:state)的所有订单。

我最初在cancelable模型中有一个范围:

OrderEvent

然后是scope :cancelable, -> { where('state = ? OR state = ?', 'pending_approval', 'pending_confirmation') } 模型中的范围:

Order

并简单地将后者用于其他目的。

这里的问题是它返回当前或过去满足条件的所有订单。

获得目前满足条件的所有订单的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

我最终使用了这样的查询:

scope :with_dates_and_current_state_cancelable, -> {
  with_dates
  .joins(:order_events)
  .where('order_events.created_at = (SELECT MAX(order_events.created_at) FROM order_events WHERE order_events.order_id = orders.id)')
  .where('order_events.state = ? OR order_events.state = ?', 'pending_approval', 'pending_confirmation')
  .group('orders.id')
}

有点难以阅读,但似乎有效。

答案 1 :(得分:0)

这里的经典解决方案是使用Rails enum

将此添加到您的订单型号:

class Order
  enum status: [ :pending_approval, :confirmed, etc.. ]
  ...
end

可以通过执行以下操作来更改状态:

# order.update! status: 0
order.pending_approval!
order.pending_approval? # => true
order.status  # => "pending_approval"

不需要order_events模型。

查询待批准的所有订单:

Order.where(status: :pending_approval)

编辑: order_event有必要列时的替代解决方案。

在名为order_event的{​​{1}}中添加一列,可以设置为1或0.将archived模型中的默认范围设置为:

order_event

假设0未归档。

现在,当您创建新订单事件时,将旧事件设置为1。

default_cope where(:archived => 0)

每当您查询等待审核时:

old_event = OrderEvent.find(params[:order_id])
old_event.update(archived: 1)
new_event = OrderEvent.create(...archived: 0)

仅显示未归档的事件。

答案 2 :(得分:0)

我想我找到了一个可能有用的查询。我没有将它转换为ActiveRecord方法,但这里是:

SELECT t.order_id
FROM
  (SELECT MAX(created_at) AS created, order_id
  FROM order_events
  GROUP BY order_id) as t
INNER JOIN order_events
ON t.order_id = order_events.order_id AND
   t.created = order_events.created_at
WHERE order_events.state = 'whatever_state_you_want'