Ruby on rails 选择集合的补码
我使用的是Rails 3.0。我有两张桌子:挂牌和优惠。一个清单Ruby on rails 选择集合的补码,ruby-on-rails,ruby-on-rails-3,activerecord,Ruby On Rails,Ruby On Rails 3,Activerecord,我使用的是Rails 3.0。我有两张桌子:挂牌和优惠。一个清单有许多优惠。报价可以是接受为真或假 我想选择每个没有accepted为true的报价的列表。我试过了 Listing.joins(:offers).where('offers.accepted' => false) 但是,由于一个清单可以有许多报价,因此这会选择每个有未接受报价的清单,即使该清单有接受的报价 如果不清楚,我想要的是集合的补码: Listing.joins(:offers).where('offers.acce
有许多
优惠。报价可以是接受
为真
或假
我想选择每个没有accepted
为true的报价的列表。我试过了
Listing.joins(:offers).where('offers.accepted' => false)
但是,由于一个清单可以有许多报价,因此这会选择每个有未接受报价的清单,即使该清单有接受的报价
如果不清楚,我想要的是集合的补码:
Listing.joins(:offers).where('offers.accepted' => true)
我目前的临时解决方案是获取所有这些数据,然后对阵列进行筛选,如下所示:
class Listing < ActiveRecord::Base
...
def self.open
Listing.all.find_all {|l| l.open? }
end
def open?
!offers.exists?(:accepted => true)
end
end
类列表true)
结束
结束
我更希望该解决方案在数据库端运行过滤。首先想到的是在数据库中执行与现在基本相同的操作
scope :accepted, lambda {
joins(:offers).where('offers.accepted' => true)
}
scope :open, lambda {
# take your accepted scope, but just use it to get at the "accepted" ids
relation = accepted.select("listings.id")
# then use select values to get at those initial ids
ids = connection.select_values(relation.to_sql)
# exclude the "accepted" records, or return an unchanged scope if there are none
ids.empty? ? scoped : where(arel_table[:id].not_in(ids))
}
我相信使用外部连接和分组可以更干净地完成这项工作,但我不会马上想到:-)谢谢!这比我以前做的要快得多。最让我感到惊讶的是,我在互联网上没有找到解决这个问题的方法——这似乎是一个比较常见的问题。警告——如果没有公认的答案,那么
ids
是空的。这将使中的not_失败,并且将不选择任何内容!我在ids
声明的正下方添加了ids |=[0]
,效果非常好。