[#] post.reload p-6ren">
gpt4 book ai didi

ruby-on-rails-3 - 将嵌套模型关联属性与包含匹配

转载 作者:行者123 更新时间:2023-12-03 14:51:37 25 4
gpt4 key购买 nike

假设我有以下模型:

class Post < ActiveRecord::Base
has_many :authors

class Author < ActiveRecord::Base
belongs_to :post

并假设 Author模型有一个属性, name .

我想通过该作者的名字搜索给定作者“alice”的所有帖子。假设有另一位作者“bob”与 alice 共同撰写了一篇文章。

如果我使用 includes 搜索第一个结果和 where :
post = Post.includes(:authors).where("authors.name" => "alice").first

您会看到该帖子现在只有一位作者,即使实际上还有更多作者:
post.authors #=> [#<Author id: 1, name: "alice", ...>]
post.reload
post.authors #=> [#<Author id: 1, name: "alice", ...>, #<Author id: 2, name: "bob", ...>]

问题好像是 includes的组合和 where ,这将范围正确地限制到所需的帖子,但同时隐藏除匹配的关联之外的所有关联。

我想以 ActiveRecord::Relation 结束用于链接,因此上面的重新加载解决方案并不是很令人满意。更换 includes来自 joins解决了这个问题,但不急切加载关联:
Post.joins(:authors).where("authors.name" => "alice").first.authors
#=> [#<Author id: 1, name: "alice", ...>, #<Author id: 2, name: "bob", ...>]
Post.joins(:authors).where("authors.name" => "alice").first.authors.loaded?
#=> false

有什么建议?提前致谢,我一直在为这个问题苦恼一段时间。

最佳答案

我看到你在做什么,正如预期的行为,至少 SQL 是这样工作的......你将作者的连接限制在authors.id = 1 的地方,那么为什么它会加载任何其他人? ActiveRecord 只获取数据库返回的行,它无法知道是否还有其他行,而无需根据 posts.id 进行另一次查询。

这是带有子查询的一种可能的解决方案,它将作为可链接的关系工作,并在一个查询中执行:

relation = Post.find_by_id(id: Author.where(id:1).select(:post_id))

如果添加包含,您将看到查询以以下两种方式之一发生:
relation = relation.includes(:authors)

relation.first
# 1. Post Load SELECT DISTINCT `posts`.`id`...
# 2. SQL SELECT `posts`.`id` AS t0_r0, `posts`.`title` AS t0_r1, ...

relation.all.first
# 1. SQL SELECT `posts`.`id` AS t0_r0, `posts`.`title` AS t0_r1, ...

因此,根据场景,ActiveRecord 决定是否在加载所有关联作者之前使用更简单的查询来查找 id。有时分两步运行查询更有意义。

关于ruby-on-rails-3 - 将嵌套模型关联属性与包含匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9205039/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com