2009-04-25 587 views
5

在我的在線商店中,如果訂單處於「已授權」狀態並且尚未有任何關聯的貨件,則該訂單已準備好發貨。現在我正在這樣做:查找所有沒有關聯has_many對象的對象

class Order < ActiveRecord::Base 
    has_many :shipments, :dependent => :destroy 

    def self.ready_to_ship 
     unshipped_orders = Array.new 
     Order.all(:conditions => 'state = "authorized"', :include => :shipments).each do |o| 
      unshipped_orders << o if o.shipments.empty? 
     end 
     unshipped_orders 
    end 
end 

有沒有更好的方法?

回答

8

你也可以使用常規的查找語法上的關聯查詢:

Order.find(:all, :include => "shipments", :conditions => ["orders.state = ? AND shipments.id IS NULL", "authorized"]) 
+0

這不起作用。由於它是has_many關聯,所以外鍵存儲在貨運表中。 – 2009-04-25 12:57:38

1

一種選擇是在訂單上放置shipment_count,它將自動更新您附加的貨件數量。然後你只需

Order.all(:conditions => [:state => "authorized", :shipment_count => 0]) 

或者,你可以得到你的手髒一些SQL:

Order.find_by_sql("SELECT * FROM 
    (SELECT orders.*, count(shipments) AS shipment_count FROM orders 
    LEFT JOIN shipments ON orders.id = shipments.order_id 
    WHERE orders.status = 'authorized' GROUP BY orders.id) 
    AS order WHERE shipment_count = 0") 

測試,使用它,因爲SQL不完全是我的包,但我認爲它很接近前向右。我將它用於生產數據庫(即MySQL)上的類似對象安排。

請注意,如果您沒有orders.status上的索引,我會強烈建議!

查詢的作用:子查詢獲取處於授權狀態的所有訂單的所有訂單計數。外部查詢過濾器僅列出出貨計數等於零的那些過濾器。

有可能是另一種方式,你可以這樣做,違反直覺一點:

經授權,不具備在發貨表中的條目
"SELECT DISTINCT orders.* FROM orders 
    LEFT JOIN shipments ON orders.id = shipments.order_id 
    WHERE orders.status = 'authorized' AND shipments.id IS NULL" 

抓住所有的訂單;)

+0

您的語法是假的,應該是:conditions => {:state =>「authorized」,:shipment_count => 0} ...換句話說,使用散列而不是數組。 – 2009-04-26 05:04:58

12

在Rails 3使用AREL

Order.includes('shipments').where(['orders.state = ?', 'authorized']).where('shipments.id IS NULL') 
相關問題