Create Rails scope for associated model
我有2个型号:
DeliverySlot has_many:orders
订单归属于:delivery_slot
送货位置限制了其可容纳的订单数量。我想创建一个合并范围以提供所有可用的交付位置。可用的交货时间是尚未达到相关订单限制的时间。
我的尝试如下:
1 | scope :available, where("limit > ?", order.count).joins(:orders) |
order.count是上面的伪代码。
要像完成设置一样执行此操作,则需要使用
Rails实际上足够聪明,可以在适当地传递它时将其用作
您需要的是对条件不明确的订单进行计数,然后将其用作子查询:
尽管如此,我还是想提出另一种使用计数器缓存的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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会自动为每个
因此,我找到了一种在SQL中执行此操作的方法。如果有人知道一种更ruby的方式而不创建数据库查询负载,请跳入。
1 2 3 4 5 6 | scope :available, joins('LEFT JOIN orders ON orders.delivery_slot_id = delivery_slots.id') .where("delivery_slots.limit > ( SELECT COUNT(*) FROM orders WHERE orders.delivery_slot_id = delivery_slots.id ) ") |
1 2 3 4 | scope :available, lambda { |delivery_slot| joins(:orders). where("limit > ?", order.count) } |
试试这个