Rails: управление прочитанными / непрочитанными сообщениями - PullRequest
2 голосов
/ 18 февраля 2010

для форумоподобного приложения мне нужна возможность показывать каждому пользователю непрочитанные (новые) сообщения.Есть ли какой-нибудь Rails плагин / гем для этой цели?

Или: есть ли какие-либо советы, чтобы сделать эту работу эффективным способом?Я думаю о дополнительной таблице базы данных, хранящей непрочитанный статус (или статус чтения?) Каждого сообщения для каждого пользователя.Но это, кажется, метод грубой силы, возможно, есть более разумное решение ...

С наилучшими пожеланиями, Георг

Ответы [ 2 ]

12 голосов
/ 22 октября 2010

Тем временем я создал плагин Rails, основанный на моей идее выше, но с более улучшенным алгоритмом.Проверьте это здесь:
http://github.com/ledermann/unread

7 голосов
/ 19 февраля 2010

Для кого это может касаться, вот мое решение. Я добавил новую таблицу для хранения статуса чтения. Строка в этой таблице показывает количество сообщений, прочитанных пользователем в данной теме. Если в теме больше сообщений, чем прочитал пользователь, это называется «непрочитанной» темой.

Использование:

# Get number of unread posts of the logged-in user:
Discussion.unread_by(current_user).count
# => 42

# Mark a topic as read
some_topic = Discussion.find(x)
some_topic.read_by!(current_user)

Простая модель "ReadStatus":

class ReadStatus < ActiveRecord::Base
  belongs_to :user
  belongs_to :discussion

  validates_presence_of :user_id, :discussion_id, :post_count
end

Выписка из модели "Обсуждение" для хранения тем и сообщений:

class Discussion < ActiveRecord::Base
  belongs_to :user
  belongs_to :topic, :class_name => 'Discussion', :foreign_key => 'discussion_id'

  named_scope :unread_by, lambda { |user| 
      { :joins => "LEFT JOIN read_statuses ON (read_statuses.user_id = #{user} AND 
                                               read_statuses.discussion_id = discussions.id)",
        :conditions => "discussions.discussion_id IS NULL
                        AND (read_statuses.user_id IS NULL) OR (read_statuses.post_count < discussions.post_count)",
        :order => 'discussions.updated_at DESC' 
      }
  }


  def read_by!(user)
    if read_status = ReadStatus.first(:conditions => { :user_id => user.id, :discussion_id => self.id })
      read_status.update_attributes! :post_count => self.post_count
    else
      ReadStatus.create! :user_id => user.id, :discussion_id => self.id, :post_count => self.post_count
    end
  end
end
...