与自身可选的has_one关联的范围

我有一个模型缩进。 我正在使用STI。 缩进可以是两种类型的销售和购买。 在购买类中,我使用可选的has_one关联。

class Purchase  '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  '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 

我在耦合这两部分查询时缺少什么?

我首先对purchasesale条款感到困惑。 但是我相信你的更新帮助我更多地理解了这个问题。

所以我所理解的是,未售出的是购买减去销售额。 以下应该给你那个清单:

 scope :unsold, lambda {includes(:sale).select { |p| !p.sale.present? } } 

更新:

这里发生的事情的简要说明:

范围并不真正完成数据库中的所有工作。 它首先对所有购买进行SQL选择,包括联合销售。 这将为您提供purchases表中的所有记录。 然后,此范围将回退到select方法上的Ruby Array 。 该方法返回所有购买p而没有sale ,这是通过否定销售购买来完成的。

希望这可以清楚范围正在做些什么。

更新2:

可连接的范围!

 scope :unsold, lambda { where('id not in (?)', Sale.pluck(:linked_indent_id)) } 

在此范围内,选择不在Salelinked_indent_id中的购买id

Rails-ey以数据库为中心的方法:

 scope :sold, -> { joins(:sale) } scope :unsold, -> { includes(:sale).where(sales: {linked_indent_id: nil}) } 

(请注意,您必须在where子句中使用表名,而不是关系名。这是’sales’,而不是’sale’。)