Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a news feed in Rails 3

I want to create an activity feed from recent article and comments in my rails app. They are two different types of activerecord (their table structures are different).

Ideally I would be able to create a mixed array of articles and comments and then show them in reverse chronological order.

So, I can figure out how to get an array of both articles and comments and then merge them together and sort by created_at, but I'm pretty sure that won't work as soon as I start using pagination as well.

Is there any way to create a scope like thing that will create a mixed array?

One of the other problems for me, is that it could be all articles and it could be all comments or some combination in between. So I can't just say I'll take the 15 last articles and the 15 last comments.

Any ideas on how to solve this?

like image 350
Cyrus Avatar asked Jun 14 '11 07:06

Cyrus


1 Answers

When I've done this before I've managed it by having a denormalised UserActivity model or similar with a belongs_to polymorphic association to an ActivitySource - which can be any of the types of content that you want to display (posts, comments, up votes, likes, whatever...).

Then when any of the entities to be displayed are created, you have an Observer that fires and creates a row in the UserActivity table with a link to the record.

Then to display the list, you just query on UserActivity ordering by created_at descending, and then navigate through the polymorphic activity_source association to get the content data. You'll then need some smarts in your view templates to render comments and posts and whatever else differently though.

E.g. something like...

user_activity.rb:

class UserActivity < ActiveRecord::Base
  belongs_to :activity_source, :polymorphic => true

  # awesomeness continues here...
end

comment.rb (post/whatever)

class Comment < ActiveRecord::Base
  # comment awesomeness here...
end

activity_source_observer.rb

class ActivitySourceObserver < ActiveRecord::Observer

  observe :comment, :post

  def after_create(activity_source)
    UserActivity.create!(
      :user => activity_source.user, 
      :activity_source_id => activity_source.id, 
      :activity_source_type => activity_source.class.to_s, 
      :created_at => activity_source.created_at, 
      :updated_at => activity_source.updated_at)
  end

  def before_destroy(activity_source)
    UserActivity.destroy_all(:activity_source_id => activity_source.id)
  end

end
like image 66
madlep Avatar answered Oct 20 '22 13:10

madlep