在rails 4/5中,我正在尝试显示项目列表,如果搜索用户喜欢或保存了这些项目,那么就在我的索引上显示某个项目。这类似于社交网络,显示帖子的提要,并允许我查看我是否已经喜欢该帖子,或显示项目列表并标记我是否已保存列表中的任何项目。
举一个简单的例子,假设我有一个User
,一个Post
和一个LikedPost
联接模型。用户可以创建帖子,然后其他用户可以喜欢这些帖子。作为用户,我可以查看帖子,还可以查看我是否喜欢其中一个帖子。
从理论上讲,这样的事情应该有效:
@posts = Post.includes(:liked_posts)
.where('liked_posts.user_id = ?', current_user.id)
.references(:liked_posts)
但实际上执行的查询仅会向我显示我喜欢的帖子。其他帖子已被过滤掉。
我很难在网上找到任何相关内容,而我能找到的内容基本上归结为'你需要编写SQL。'任何提示/建议?
答案 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%,但开发时这两种方法都不是特别慢实际记录很少的数据库。
我也很欣赏有关清理它的想法。