在一个由 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
但它破坏了代码