2017-01-30 73 views
1

我有訂單模型和下面一個範圍容器模型:Rails的活動記錄範圍

class Order < ActiveRecord::Base 
    has_many :containers, inverse_of: :order, dependent: :destroy 
end 

class Container < ActiveRecord::Base 
    scope :full_pickup_ready, -> { where.not(full_pickup_ready_date: nil) } 
end 

順序模式有一個現場電話quantity代表集裝箱訂單的數量要求但不一定是容器關聯的大小,因爲並非所有容器數據都是在創建訂單時輸入的。

我想根據具有full_pickup_ready_date的容器的計數是否小於訂單的數量字段,訂單模型上有一個作用域。

我知道我可以使用的命令模式合併來訪問這樣的容器範圍:

def self.at_origin 
    joins(:containers).merge(Container.full_pickup_ready).uniq 
end 

,但我怎麼能限制範圍的訂單,其中容器用full_pickup_ready_date總數爲少於訂單上的數量字段?

UPDATE: 這是相當接近的,但我不認爲使用select是有效的:

includes(:containers).select {|o| o.containers.full_pickup_ready.size < o.quantity } 
+0

什麼是'carrier_collected_full'對象?它是一個集合還是一個容器? – kurenn

+0

對不起,這是我複製錯誤的範圍(我有幾個範圍與類似的問題)。它應該是容器模型'full_pickup_ready'中的範圍。我改變了上面的使用'full_pickup_ready'範圍。 –

回答

2

如果你願意放棄範圍的再利用上Container,那麼你應該能夠使用類似:

# scope on Order 
joins(:containers) 
    .group("orders.id") 
    .having("count(CASE WHEN full_pickup_ready_date THEN 1 END) < orders.quantity") 
+0

謝謝 - 在計數中使用CASE是聰明的,給我我想要的。我確實必須將其更改爲'CASE WHEN full_pickup_ready_date不爲NULL,然後完成「。當它讓我(大約7小時)給予獎勵時, –

1

我認爲你需要得到這個SQL查詢來爲你工作。所以我們的想法是正確地獲取SQL查詢,然後將其轉換爲「Rails」。

SQL

如果我是正確的,這應該是你要實現的SQL查詢。也許你可以嘗試在你的rails db

SELECT orders.* 
FROM orders JOIN containers 
WHERE containers.id = orders.id 
AND ( 
    SELECT COUNT(containers.id) 
    FROM containers 
    WHERE containers.full_pickup_ready_date IS NOT NULL 
) < orders.quantity; 

ActiveRecord的

如果這是正確的查詢,那麼我們就可以做到這一點使用Rails

Order.joins(:containers).where("(SELECT COUNT(containers.id) FROM containers WHERE containers.full_pickup_ready_date IS NOT NULL) < orders.quantity") 

這應返回一個ActiveRecord關係。你也可以這樣做:

sql = %{ 
    SELECT orders.* 
    FROM orders JOIN containers 
    WHERE containers.id = orders.id 
    AND ( 
    SELECT COUNT(containers.id) 
    FROM containers 
    WHERE containers.full_pickup_ready_date IS NOT NULL 
) < orders.quantity; 
}.gsub(/\s+/, " ").strip 

Order.find_by_sql(sql) 

只需在類方法(比範圍恕我直言,更好)添加此,你很好去。

所以,你的Order類應該是這樣的:

class Order < ActiveRecord::Base 
    has_many :containers, inverse_of: :order, dependent: :destroy 

    def self.gimme_a_query_name 
    joins(:containers).where("(SELECT COUNT(containers.id) FROM containers WHERE containers.full_pickup_ready_date IS NOT NULL) < orders.quantity") 
    end 

    def self.gimme_another_query_name 
    sql = %{ 
     SELECT orders.* 
     FROM orders JOIN containers 
     WHERE containers.id = orders.id 
     AND ( 
     SELECT COUNT(containers.id) 
     FROM containers 
     WHERE containers.full_pickup_ready_date IS NOT NULL 
    ) < orders.quantity; 
    }.gsub(/\s+/, " ").strip 
    find_by_sql(sql) 
    end 
end 

我沒有辦法去嘗試這一點,但它應該與一些的調整工作,以獲得SQL查詢的權利。

我希望這個幫助!

+0

謝謝,我可以看到這將如何工作,但來自@ gwcodes的答案更簡潔一點,所以我會選擇這個答案。 –