Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Acts-as-readable Rails plugin Issue

I'm using Intridea's Acts as Readable Rails plugin for a messaging system I'm currently building. I've defined my message class accordingly:

class Post < ActiveRecord::Base
  acts-as-readable
end

And everything seems to be working according to plan, but when trying to make the app show unread messages in my message view, I run into problems.

Their example: (I've changed underscores to hyphens due to formatting issues)

bob = User.find_by_name("bob")

bob.readings                      # => []

Post.find_unread_by(bob)          # => [<Post 1>,<Post 2>,<Post 3>...]
Post.find_read_by(bob)            # => []

Post.find(1).read_by?(bob)        # => false
Post.find(1).read_by!(bob)        # => <Reading 1>
Post.find(1).read_by?(bob)        # => true
Post.find(1).users_who_read       # => [<User bob>]

Post.find_unread_by(bob)          # => [<Post 2>,<Post 3>...]
Post.find_read_by(bob)            # => [<Post 1>]

bob.readings                      # => [<Reading 1>]

So it seems that if I wanted to list the number of unread messages sitting in a mailbox (for example Inbox (39) ), I should be able to do something like:

<%= Post.find_unread_by(current-user).count %>

But to no avail. I always seem to get stuck on the simple view issues after everything's set. Any ideas?

like image 885
btw Avatar asked Aug 22 '08 17:08

btw


1 Answers

The following will work

<%= Post.find_unread_by(current_user).size %>

or

<%= Post.find_unread_by(current_user).length %>

However if you check your development.log you should see that it gets the unread count by

  1. Retrieving all the posts
  2. Retrieving all the posts read by the user
  3. Removing all of 2. from 1. in ruby

This will be very bad performance wise with lots of posts.

A better way would be to retrieve the posts read by the current user and then use ActiveRecord::Calculations to get a count without retrieving all the posts in the database

Post.count(:conditions => [ "id NOT IN (?)", Post.find_read_by(current_user)])

This should go into your Post model to follow best practices of not having finders in the view or controller

Post.rb

def self.unread_post_count_for_user(user)
  count(:conditions => [ "id NOT IN (?)", Post.find_read_by(user)])
end

Then your view will just be

<%= Post.unread_post_count_for_user(current-user) %>
like image 141
russtbarnacle Avatar answered Sep 30 '22 19:09

russtbarnacle