関連付けを参照しているため、orders.count
代わりに使用する必要があるセットアップがあるようにこれを行うには。order.count
これにより、ActiveRecord は次のようなクエリを組み立てるようになりますSELECT COUNT(*) FROM orders WHERE delivery_slot_id = 1
。
where
Rails は、適切に渡すと条件のサブクエリとして使用できるほどスマートです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
orders_count
Rails は、各 の列を自動的にインクリメントおよびデクリメントしDeliverySlot
ます。また、インデックスが作成されているため、クエリが非常に高速です。