2013-05-27 3 views
0

을위한 레일 범위를 만들기나는이 개 모델이 관련된 모델

배달 슬롯들이 보유 할 수있는 방법 많은 주문의 제한이 delivery_slot : 주문을 belongs_to 주문. 사용 가능한 모든 게재 슬롯을 제공하는 범위를 만들고 싶습니다. 사용 가능한 게재 슬롯은 관련 주문의 한도에 도달하지 않은 슬롯입니다.

scope :available, where("limit > ?", order.count).joins(:orders) 

order.count은 의사가 위입니다 : 같은

내 시도가 보인다.

답변

2

을이 당신이 협회를 참조하고 있기 때문에 orders.count 대신 order.count을 사용해야합니다 설치 프로그램을 가지고있는 것처럼하려면. 그러면 ActiveRecord가 SELECT COUNT(*) FROM orders WHERE delivery_slot_id = 1과 비슷한 쿼리를 조합합니다.

레일스는 적절하게 패스 할 때 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 

레일이 자동으로 증가하고 각 DeliverySlot에 대한 orders_count 열을 감소하고, 것, 그것은 터무니입니다 빠른 쿼리.

+0

와우, 고마워. 나는 카운터 캐시에 대해 몰랐다. 나는 지금 그것을 구현했습니다. –

+0

@ MarkRobinson 이봐, 나는 당신이 제안한 편집을 보았고, 나는'class DeliverySlot coreyward

0
scope :available, lambda { 
    |delivery_slot| joins(:orders). 
     where("limit > ?", order.count) 
} 

+0

죄송합니다, 이것은 작동하지 않습니다 - 람다 함수에 대한 나의 이해는 당신이 당신이 그것을 호출 할 때마다 변하는 변수를 전달할 수있게 해줍니다. 내가 원하는 것을 매번 바꿀 필요는 없습니다. –

+0

흠 ... 나중에 왜'delivery_slot'을 매개 변수로 λ 블록에 전달하지만 결코 사용하지 않습니까? – nzifnab

0

그래서 내가 SQL에서 그것을 할 수있는 방법을 찾아보십시오. 사람이 데이터베이스 쿼리의 부하를 생성하지 않고 더 루비 방법을 알고있는 경우에 이동하십시오.

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) 
    ")