【问题标题】:Find all objects with no associated has_many objects查找没有关联 has_many 对象的所有对象
【发布时间】:2009-04-25 02:37:39
【问题描述】:

在我的在线商店中,如果订单处于“授权”状态并且还没有任何关联的发货,则可以发货。现在我正在这样做:

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

有没有更好的办法?

【问题讨论】:

    标签: ruby-on-rails activerecord associations


    【解决方案1】:

    在 Rails 3 中使用 AREL

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

    【讨论】:

      【解决方案2】:

      您也可以使用普通的 find 语法查询关联:

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

      【讨论】:

      • 这行不通。由于是 has_many 关联,所以外键存储在 shipping 表中。
      • 这就是我们加入 NULL 标识符的原因
      • 是的,我的错(我不擅长 SQL)。无论如何,这是可行的,除了你必须用“状态”替换“状态”(对于我的特殊情况)并在“shipments.id”之前添加一个“和”。进行这些更改,我会将其标记为答案。
      【解决方案3】:

      一种选择是在 Order 上设置 shipping_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"
      

      获取所有已授权且在发货表中没有条目的订单;)

      【讨论】:

      • 你的语法是假的,应该是 :conditions => { :state => "authorized", :shipment_count => 0 }...换句话说,使用哈希,而不是数组。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多