Rails:查找没有“has_one”记录的记录

8

我有一个应用程序有两个模型。Foo拥有一个Bar,而Bar属于Foo。

现在,要创建一个Foo,你必须创建一个属于它的Bar,但在我的生产应用程序中似乎有一个没有Bar的Foo被创建了,这导致了500错误。

现在,问题来了:

我可以轻松地搜索:Bar.where(:foo => nil)。但是孤儿bars不是问题,这并不能告诉我需要的信息。

我需要找到Bar为nil的那个Foo。但数据库将关系存储在Bars表中,即BarsTable中有foo_id,FoosTable中没有任何内容告诉我缺少一个bar。

当我使用Foo.find(#).bar时,对于一个虚假记录,我得到的是nil,但我有很多记录。

因此,有人可以告诉我如何构建一个查询来返回丢失其Bar的一个Foo吗?

谢谢!

4个回答

8

我不确定Ruby代码会是什么,但我认为SQL应该是这样的:

SELECT * FROM Foo WHERE id NOT IN (SELECT foo_id FROM Bar)


4
这很有效!在Rails中只需使用Foo.where("id NOT IN (SELECT foo_id FROM Bar)")。 谢谢! - Andrew
在我看来,正确的 AR 方法是:Foo.joins(:bar),这将导致 SQL 查询为 SELECT \foos`.* FROM `foos` INNER JOIN `bars` ON `bars`.`foo_id` = `foos`.`id`。你还可以进一步优化:Foo.includes(:bar).joins(:bar)` 可能会为您节省几个后续对数据库的请求。 - Isaac Betesh

2

另一种方法(不使用SQL)是执行以下操作:

Foo.all.select{ |f| !f.bar }

这将返回一个数组,其中包含没有相关Bar对象的Foo对象。

在这种方法中,您不依赖于特定的表信息。如果将来外键列在Foo -> Bar关联中更改,此方法将继续工作。


这样做的性能会大大降低,因为它会导致AR对象被获取和实例化。 - kranzky

2

未来的用户访问者可以通过以下方式完成此操作 -

最初的回答:

Foo.all.where.not(id: Bar.pluck(:belongs_to_id))

这段代码执行了两次查询,一次是pluck操作,另一次是查询Foo表中未包含pluck结果的数据。

0
使用 left_outer_join 来完成这个任务。
Foo.left_outer_joins(:bar).where(bars: { id: nil })

Rails为这种情况添加了一个很方便的方法。
Foo.where.missing(:bar)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接