Rails-通过包括关联在内的所有关系获得所有记录,包括未关联的记录

时间:2019-02-21 09:22:31

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

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

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.favourites.first之类的收藏夹,这有点不理想。

有没有更好的查询可以在Favourite上进行搜索的地方得到所有用户尚未收藏的电影结果?也许还有其他东西。

我已经做了类似的事情

Favourite.includes(:movie)....

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

2 个答案:

答案 0 :(得分:1)

我将首先查询当前用户的收藏电影列表,并将其ID存储在Set中:

when: item.tags in ansible_run_tags

使用这样的# 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 %> 的查询更糟糕。

答案 1 :(得分:1)

您可以对left join使用单个查询:

res = Movie.left_joins(:favourites).where(fauvorites:{ user_id: [current_user.id, nil]}).
       select(Movie.arel_table[Arel.star], "(favourites.id is null) as is_favourited_by_user")
res.first.is_favourited_by_user # 0/1

返回的Movie对象将生成is_favorited_by_user字段,该字段指示该用户是否偏爱特定电影。