views:

45

answers:

2

Hi, I'm currently developing an application whereby a user clicks a button and they're offered up a new page of content, and was wondering how I would go about hiding or skipping past those that the user has already interacted with (a separate table stores the post_id and user_id for each view).

I currently use this code in the model for displaying a random page:

   def self.random
       if (c = count) != 0
         find(:first, :offset =>rand(c))
       end
   end

The user authentication system is built off of Authlogic, and I have User, Post and View models.

So if a user has already seen a post "foo", how would I not display that in the future and instead serve up a random "bar".

Thanks

A: 

Steve,

I would set a boolean field for each post called "read" (default => false).

Upon firing the "show" action of your controller (and any other action you consider the person seeing the post), you can automatically set that to true and perform a save without validation. When you then show your list of records, you can add the condition .where("read = ?", false).

Of course, you can decide whether you want to give users the flexibility of setting individual posts to 'unseen' or 'unread' - if you want to do that it's the subject of another question :).

sscirrus
How would this work with many users to a single post though? Would this method work with displaying posts one at a time, as opposed to a list of all posts? Thanks.
Steve F
A: 

You could store an array of viewed post ids on the session in the show action of the posts_controller. EDIT -- find random post not already viewed. Not tested, but the idea is here:

def show_random_post
  while (id == nil || (session[:viewed_posts] ||= []).include?(id)) # initialize array if it hasn't been initialized
    id = rand(Post.count) + 1
  end
  session[:viewed_posts] << id 
  @post = Post.find(id)
  # etc.
end

Do you want to keep a record of viewed posts between sessions?

EDIT: If you want to keep a user-level record of viewed posts between sessions, you'll probably want to do it at the db level. Since this means a many-to-many relationship between users and posts, you'll likely want to manage that with a relational table, and the best way to do that in Rails is with has_many :through. Something like (again, not tested):

class ViewedPostRecord < ActiveRecord::Base
  belongs_to :user
  belongs_to :post
end

class User < ActiveRecord::Base
  has_many :viewed_post_records
  has_many :viewed_posts, :class => 'Post', :through => :viewed_post_records
end

class PostsController < ApplicationController
  def show_random_post
      while (id == nil || current_user.viewed_posts.map(&:id).include?(id))
        id = rand(Post.count) + 1
      end
      @post = Post.find(id)
      current_user.viewed_posts << @post 
      # etc.
    end
end
Dave Sims
Hi Dave, thanks for the answer. Looks like a good approach. Yes, I'd like to keep a record of viewed posts between sessions if possible. Thanks.
Steve F