构建项目索引时,如何显示用户喜欢/已加星标

时间:2016-09-13 02:14:52

标签: ruby-on-rails

在rails 4/5中,我正在尝试显示项目列表,如果搜索用户喜欢或保存了这些项目,那么就在我的索引上显示某个项目。这类似于社交网络,显示帖子的提要,并允许我查看我是否已经喜欢该帖子,或显示项目列表并标记我是否已保存列表中的任何项目。

举一个简单的例子,假设我有一个User,一个Post和一个LikedPost联接模型。用户可以创建帖子,然后其他用户可以喜欢这些帖子。作为用户,我可以查看帖子,还可以查看我是否喜欢其中一个帖子。

从理论上讲,这样的事情应该有效:

@posts = Post.includes(:liked_posts)
             .where('liked_posts.user_id = ?', current_user.id)
             .references(:liked_posts)

但实际上执行的查询会向我显示我喜欢的帖子。其他帖子已被过滤掉。

我很难在网上找到任何相关内容,而我能找到的内容基本上归结为'你需要编写SQL。'任何提示/建议?

2 个答案:

答案 0 :(得分:0)

好的,那么在你的索引页面上你有一个帖子列表吗?并为每个帖子...你显示的名称或东西?为什么没有像:

<%= image_tag 'heart.png' if post.liked_by?(current_user) %>

在名称旁边的页面上,然后在帖子模型中

 def liked_by?(user)
    self.liked_posts.where(:user_id => user.id).exists?
 end

(注意:未检查错别字和小错误)

答案 1 :(得分:0)

我想我已经考虑过另一个可行的解决方案了,所以我发布在这里以防将来有人偶然发现这个问题,虽然这个解决方案并不觉得非常'轨道'并且让我的控制器变得混乱。

无论如何,我的索引看起来像这样:

def index
  @posts = Post.all # in reality, paginated or limited
  these_posts = []
  @posts.each do |post|
    these_posts << post.id
  end

  @liked_posts = LikedPost.where(user_id: current_user)
                          .where(post_id: these_posts)

  @liked_posts_hash = Hash.new(false)
  @liked_posts.each do |liked_post|
    @liked_posts_hash[liked_post.post_id] = true
  end

  @posts.each do |post|
    post.liked = @liked_posts_hash[post.id] #liked is an attr_accessor
  end
end

因此,与Taryn更清晰的回应相比,这是一个额外的复杂性。但是(以两次运行你的posts数组和一次你的likes_posts数组为代价)它确实将数据库查询限制为两个而不是n + 1.

回顾一下响应时间,在我的开发机器中,以20个帖子的方式构建视图大约需要100毫秒而不是每个对象查询130毫秒,因此大约快25%,但开发时这两种方法都不是特别慢实际记录很少的数据库。

我也很欣赏有关清理它的想法。