我有一个模型缩进。我正在使用STI。缩进可以是两种类型的销售和购买。在购买类中,我使用可选的has_one关联。
class Purchase < Indent
has_one :sale , :class_name => 'Sale', :foreign_key => 'linked_indent_id'
# Make it work.
scope :unsold, lambda {includes(:sale).where('id not in (select distinct linked_indent_id from indents)')}
end
class Sale < Indent
belongs_to :purchase , :class_name => 'Purchase', :foreign_key => 'linked_indent_id'
end
我只需要购买类的范围,我可以使用该范围找到所有未与销售相关联的购买。
我使用Rails 3.2和Postgres作为数据库。
更新
生成的查询如下。
SELECT "indents".* FROM "indents" WHERE "indents"."type" IN ('Purchase') AND
(id not in (select distinct linked_indent_id from indents)) ORDER BY indent_date DESC
以下部分查询工作正常。
=# select distinct linked_indent_id from indents;
linked_indent_id
------------------
15013
15019
(3 rows)
这也很好。
SELECT "indents".* FROM "indents" WHERE "indents"."type" IN ('Purchase') AND
(id not in (15013, 15019)) ORDER BY indent_date DESC
在将这两部分查询联系起来时,我缺少什么?
答案 0 :(得分:1)
我首先对术语purchase
和sale
感到困惑。但是我相信你的更新有助于我更多地理解这个问题。
所以我所理解的是,未售出的是购买减去销售额。以下应该给你那个清单:
scope :unsold, lambda {includes(:sale).select { |p| !p.sale.present? } }
更新:
简要说明这里发生的事情:
范围并不真正完成数据库中的所有工作。它会对所有购买进行SQL选择,包括首先加入的销售。这将为您提供purchases
表中的所有记录。然后,此范围将回退到Array
方法上的Ruby select
。该方法返回所有购买p
而没有sale
,这是通过否定销售购买来完成的。
希望这可以清楚范围正在做些什么。
更新2:
可链接的范围!
scope :unsold, lambda { where('id not in (?)', Sale.pluck(:linked_indent_id)) }
在此范围内,选择了id
Sale
以内的linked_indent_id
次购买。
答案 1 :(得分:0)
Rails-ey以数据库为中心的方法:
scope :sold, -> { joins(:sale) }
scope :unsold, -> { includes(:sale).where(sales: {linked_indent_id: nil}) }
(请注意,您必须使用where
子句中的表名,而不是关系名称。这是&#39;销售&#39;,不是&#39;销售&#39;。)< / p>