gpt4 book ai didi

ruby-on-rails - 急切加载关联的第一条记录

转载 作者:行者123 更新时间:2023-12-04 04:38:20 29 4
gpt4 key购买 nike

在一个由 Rails 应用程序制作的非常简单的论坛中,我在索引操作中从数据库中获得了 30 个主题,如下所示

def index

@topics = Topic.all.page(params[:page]).per_page(30)

end

但是,当我在 views/topics/index.html.erb 中列出它们时,我还希望能够访问每个主题中的第一篇文章以显示在工具提示中,以便用户滚动时可以阅读第一篇文章无需点击链接。因此,在索引中每个帖子的链接中,我将以下内容添加到数据属性中
topic.posts.first.body

每个链接看起来像这样
<%= link_to simple_format(topic.name), posts_path(
:topic_id => topic), :data => { :toggle => 'tooltip', :placement => 'top', :'original-title' => "#{ topic.posts.first.body }"}, :class => 'tool' %>

虽然这工作正常,但我担心这是一个 n+1 查询,即如果有 30 个主题,它会执行 30 次
 User Load (0.8ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Post Load (0.4ms) SELECT "posts".* FROM "posts" WHERE "posts"."topic_id" = $1 ORDER BY "posts"."id" ASC LIMIT 1 [["topic_id", 7]]

我注意到 Rails 对其中的一些进行了自动缓存,但我认为可能有一种方法可以以不同的方式编写索引操作以避免某些 n+1 问题,但我可以弄清楚如何做。我发现我可以
include(:posts) 

急切地加载帖子,就像这样
@topics = Topic.all.page(params[:page]).per_page(30).includes(:posts)

但是,如果我知道我只想要每个主题的第一篇文章,有没有办法指定它?如果一个主题有 30 个帖子,我不想急切地加载所有帖子。

我试着做
.includes(:posts).first

但它破坏了代码

最佳答案

这似乎对我有用,所以试一试,看看它是否适合你:

Topic.includes(:posts).where("posts.id = (select id from posts where posts.topic_id = topics.id limit 1)").references(:posts)

这将创建一个 依赖子查询其中 posts子查询中的 topic_id 与 topics 匹配父查询中的 id。与 limit 1子查询中的子句,结果是每个 Topic行将只包含 1 个匹配的 Post行,由于 includes(:post) 急切加载.

请注意,将 SQL 字符串传递给 .where 时,它引用了一个预先加载的关系, references应该附加方法来通知 ActiveRecord 我们正在引用关联,以便它知道在后续查询中执行适当的连接。显然,它在技术上可以在没有该方法的情况下工作,但是您会收到弃用警告,因此您最好将其放入,以免在 future 的 Rails 更新中遇到问题。

关于ruby-on-rails - 急切加载关联的第一条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19353507/

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