要做到这一点,就像你有设置一样,你需要使用orders.count
而不是order.count
因为你指的是关联。这将提示 ActiveRecord 组装一个看起来像SELECT COUNT(*) FROM orders WHERE delivery_slot_id = 1
.
Rails 实际上足够聪明,可以在您where
适当地传递它时将其用作条件中的子查询,例如 la where('limit > ', orders.count)
。但正如您可能看到的,如果它是预编译的,这将不起作用,因为查询在条件中使用了显式 ID。
相反,您需要计算条件不明确的订单,然后将其用作子查询:where('limit > ?', Order.where(delivery_slot_id: 'delivery_slots.id').count)
。如果您尝试单独运行订单计数的查询,它将失败delivery_slots
,但因为它在此处的子查询中,您应该一帆风顺。
我想提出另一种完全这样做的方法,使用计数器缓存:
class AddCounterCacheToDeliverySlots < ActiveRecord::Migration
class DeliverySlot < ActiveRecord::Base; end
def change
add_column :delivery_slots, :orders_count, :integer, default: 0
add_index :delivery_slots, [:orders_count, :limit]
DeliverySlot.reset_column_information
DeliverySlot.find_each do |delivery_slot|
DeliverySlot.update_counters delivery_slot.id, orders_count: delivery_slot.orders.count
end
end
end
class Order < ActiveRecord::Base
belongs_to :delivery_slot, counter_cache: true
end
class DeliverySlot < ActiveRecord::Base
has_many orders
scope :available, where('orders_count < limit')
end
Rails 会自动递增和递减orders_count
each 的列DeliverySlot
,并且因为它是索引的,所以查询起来快得离谱。