2

在我的应用程序中,当 aUserCommenta中生成 a 时PostNotifications会生成将该评论标记为未读。

class Notification < ActiveRecord::Base
  belongs_to :user
  belongs_to :post
  belongs_to :comment

class User < ActiveRecord::Base
  has_many :notifications

class Post < ActiveRecord::Base
  has_many :notifications

我正在制作一个索引页面,其中列出了一个用户的所有帖子以及该用户的每个帖子的通知计数

# posts controller
@posts = Post.where(
    :user_id => current_user.id
  )
  .includes(:notifications)

# posts view
@posts.each do |post|
  <%= post.notifications.count %>

这不起作用,因为它计算所有用户的通知。为单个用户计算通知而不在每个帖子中运行单独查询的有效方法是什么?

4

3 回答 3

1

找到了解决方案!

# posts controller
@posts = Post.where(… 
@notifications = Notification.where(
            :user_id => current_user.id,
            :post_id => @posts.map(&:id),
            :seen => false
        ).select(:post_id).count(group: :post_id)

# posts view
@posts.each do |post|
  <%= @notifications[post.id] %>

似乎足够高效。

于 2013-11-09T06:05:28.343 回答
0

我建议创建一个小类来封装通知集合的逻辑:

class NotificationCollection
  def self.for_user(user)
    new(Notification.where(user_id: user.id))
  end

  def initialize(notifications)
    @notifications = notifications
  end

  include Enumerable
  def each(&block)
    @notifications.each(&block)
  end

  def on_post(post)
    select do |notification|
      notification.post_id == post.id
    end
  end
end

然后,在您的控制器上:

@user_notifications = NotificationCollection.for_user(current_user)
@posts              = Post.where(user_id: current_user.id)

最后,在你看来:

@posts.each do |post|
  <%= @user_notifications.on_post(post).count %>
end

这样,您只需要为每个用户执行一个通知查询 - 性能不如COUNT()在数据库上执行,但如果单个用户的通知保持在数百个以下就足够了。

于 2013-11-09T03:38:45.690 回答
0

你可以这样做:

@posts=Post.joins(:notifications).where('notification.user_id' => current_user.id)

notification.user_idcurrent_user的通知id在哪里

于 2013-11-09T03:31:16.530 回答