首页 > 解决方案 > Rails - 获取所有记录有许多通过关系,包括未关联的记录

问题描述

我有以下具有许多直通关系的课程。

class Movie < ApplicationRecord
  has_many :favourites, dependent: :destroy
  has_many :users, through: :favourites
end

class Favourite < ApplicationRecord
  belongs_to :user
  belongs_to :movies
end


class User < ApplicationRecord
  has_many :favourites, dependent: :destroy
  has_many :movies, through: :favourites
end

我有一个搜索页面,允许用户按名称搜索电影。但我还需要显示当前用户是否喜欢这部电影。所以基本上我有一个看起来像这样的查询(减少以保持相关性):

@movies = Movie.includes(favourites: :user)
               .where(favourites: { user: [current_user, nil] })

所以在上面,我得到了所有的电影,我也试图得到所有当前用户的收藏,但如果电影还没有被收藏,也会返回结果。

问题是,我现在必须检索用户最喜欢的内容,例如:

@movies.each do |movie|
  movie.favourites.first # current users fav movie
end

因为我正在对 Movie 执行查询,所以我得到了所有用户的收藏夹集合(这很有意义),但过滤到当前用户。因此,我需要通过并检查最喜欢的东西并不理想movie.favourites.first- 感觉有点奇怪。

是否有更好的查询可以执行,我可以在其中执行搜索Favourite并获取用户尚未收藏的所有电影结果?或者也许是别的东西。

我已经完成了类似的事情

Favourite.includes(:movie)....

但我不确定如何获得所有结果,包括用户不喜欢的电影结果。

标签: ruby-on-railsrubyactiverecordruby-on-rails-5

解决方案


我会先查询当前用户最喜欢的电影列表,并将他们的 id 存储在Set

# in the controller
require `set`
@favorite_movies_ids = Set.new(Favourite.where(user: current_user).pluck(:movie_id))

使用这样的方法,Set您可以通过非常有效O(1)的操作检查当前用户是否收藏了特定电影并在页面上显示该信息——例如:

# in the view
<% @movies.each do |movie| %>
  <%= 'favorite!' if @favorite_movies_ids.include?(movie.id) %>
  # ...
<% end %>

我想在这种情况下,两个简单的查询不会比数据库中一个复杂JOIN的查询差多少。


推荐阅读