Facebook-style news feed?

I've tried googling for more information on this, but I've come up empty.

Has anyone implemented a facebook-style news feed on their rails app? Here's my situation. I have a recipe-sharing site, and I'd like to have a feed that shows a user when a few different actions happen to them or their recipes (like adding as a favorite, adding as a follower, etc.).

I don't know how to essentially take three or four queries and combine them into one feed that I can display in my view chronologically. Is there a plugin for this that I don't know about?

Thanks for the help; any tips are helpful.

I’m sure it can be done in one query, but this is how I’d do it:

combined = Array.new combined << Comment.all combined << Favorite.all

…etc. Though you’ll want to set limits to the above

@feed = combined.sort { |x,y| y.created_at <=> x.created_at }

…and then when looping through in your views, use “object.class.to_s” to see what it is, and change the icon, style, etc accordingly.

I look forward to any other replies which have a better way of doing it, 'cause multiple queries isn’t great, but a news feed can be cached very easily so I don’t see much problem with the above! :slight_smile:

Opps sorry, obviously you can’t add each result to an array and sort them, you’d have to merge the resulting arrays! :wink:

That makes sense -- I hadn't thought about stuffing the queries into an array. If I get some time today I might fiddle with that and see how it works.

Thanks!!

You could also create an Actions model which has_many favourites/comments/ect. which seems like a more sensible solution; it’d join and include all the data from the sources tables for you in one query. :slight_smile:

Ashley Williams wrote:

You could also create an Actions model which has_many favourites/comments/ect. which seems like a more sensible solution; it'd join and include all the data from the sources tables for you in one query. :slight_smile:

On Wed, Dec 24, 2008 at 4:19 PM, Dave Amos <rails-mailing-list@andreas-s.net

Clever! I'm not sure I'm clever enough to implement it correctly, though. I created a Newsfeed model and did the has_many/belong_to stuff, but I'm not sure how to do my controller code.

Lets say I wanted to have a feed of all actions a user takes (comments, recipes posted, favorites, etc.). I tried:

@feed = Newsfeed.find(:all, :conditions => ["user_id = ?", @user.id])

But I get this error: Mysql::Error: #42S02Table 'cookingfriend_development.newsfeeds' doesn't exist: SELECT * FROM `newsfeeds`

I think I need a database? How else do I query the model?

You'd have to have some polymorphic columns in an "actions" table, something like:

id #=> 1 comment_id #=> 15 favourite_id #=> nil user_id #=> 10 created_at #=> Wed Dec 17 03:14:41 0000 2008

Then you can do something like:

Newsfeed.all(:conditions => { :user_id => 1 }, :include => [:comment, :favourite], :limit => 25)

…At least I THINK that'd work, but I think it would — something similar anyhow! :slight_smile:

Ashley Williams wrote:

You'd have to have some polymorphic columns in an "actions" table, something like:

id #=> 1 comment_id #=> 15 favourite_id #=> nil user_id #=> 10 created_at #=> Wed Dec 17 03:14:41 0000 2008

Then you can do something like:

Newsfeed.all(:conditions => { :user_id => 1 }, :include => [:comment, :favourite], :limit => 25)

�At least I THINK that'd work, but I think it would � something similar anyhow! :slight_smile:

On Wed, Dec 24, 2008 at 5:16 PM, Dave Amos

Thanks, duh, that makes sense to me. I just created the database, and now I'm going to start writing methods that connect everything with the actions table so I can get some data in there.

I have a performance-related question. I don't think it'd be too demanding to ask the action table "show me everything this user has done" because it's just a :conditions => [:user_id = 1}. How crazy is it to ask the actions table "show me every time someone else favorites or comments on my recipe"? I believe this is possible with the actions table you have laid out, but will it take a while to grind out of the database?

Its defiantly possible, though I'm not that good with rails yet, so I'm not sure exactly how you add conditions on other tables. But I don't think the performance would be that bad, it'd only have to span a few tables, which isn't that bad considering an average profile page would do the same; plus it can be cached a lot too.

Ashley Williams wrote:

Its defiantly possible, though I'm not that good with rails yet, so I'm not sure exactly how you add conditions on other tables. But I don't think the performance would be that bad, it'd only have to span a few tables, which isn't that bad considering an average profile page would do the same; plus it can be cached a lot too.

On Wed, Dec 24, 2008 at 6:27 PM, Dave Amos

Yeah, good point. If the table got crazy huge, I could start cutting off really old entries to minimize the calculations.

Thanks so much for the the help! I've already got a little feed that shows you your recent activity, and I think it's trivial to create feeds for all activity your friends have taken and all activity on recipes you created. This is exciting! :slight_smile:

Well it would be paginated, only X at a time will be grabbed for each page — 1-25, 26-50, 51-75, or something. Wont make much difference at a million rows than when you had only a handful! :slight_smile:

Good luck! :slight_smile:

Personally, I'd probably take the approach of adding a 'feed_item' table to the database and tie it to the user with a 'has_many' relationship

then when user x updates their favourites, you can put something like "#{user.name} has added #{recipe.name} to their favourites" into the feed_item table with a user_id passed in as a parameter, and you can make these feed items appear on the homepage of whoever is following or is friends with this user...

no plugins required (i don't think anyway)

Nellboy wrote:

Personally, I'd probably take the approach of adding a 'feed_item' table to the database and tie it to the user with a 'has_many' relationship

then when user x updates their favourites, you can put something like "#{user.name} has added #{recipe.name} to their favourites" into the feed_item table with a user_id passed in as a parameter, and you can make these feed items appear on the homepage of whoever is following or is friends with this user...

no plugins required (i don't think anyway)

On Dec 24, 8:41�pm, "Ashley Williams" <a.j.r.willi...@googlemail.com>

I don't think your method is very different from the one Ashley and I were talking about. I created an "actions" table and tied it to the user table. The thing is, I also tied it to my recipes, favorites, and comments table. That way, whenever anyone adds a recipe, makes a recipe a favorite, or adds a comment, an entry is added to the "actions" table. That entry includes the id of the user so I know who did it.

When I list my feed, the view code is (truncated example):

<% @friendfeed.each do |friendfeed| %>    <%= link_to friendfeed.user.login, :controller => "users", :action => "show", :id => friendfeed.user.id %> favorited <%= link_to friendfeed.recipe.title, :controller => "recipes", :action => "show", :id => friendfeed.recipe.id %> <% end %>

Hi Dave

I don't see the need to tie the 'feed_entry' to any other models except for the user. All that's being passed to the table are strings, and you only want to see the messages associated with a certain user's network (i.e. other users)... Or maybe you want to see messages associated with recipes.

It really just depends on what you want to do... it's all possible (that's the beauty of it!!!)

cheers for the thoughts