views:

68

answers:

2

How do you merge models so that I can have the last 10 Posts, Feed Entries and Private Messages displayed in order?

Posts are stored in the "Post" model and ordered on "created_at"

Feed Entries are stored in "Planet" and ordered on "published_at"

Private Messages are stored in "Message" and need to be filtered with:

:conditions => "receiver_id = #{current_user.id}"

and ordered on "created_at"

+2  A: 

I would use a Proxy class. The class can store the ActiveRecord object reference and the field for sorting.

class ActivityProxy
  attr_accessor :object, :date
  def initialize(object, date)
    self.object = object
    self.date = date
  end
end

Then you load your objects.

activity = []
activity += Post.all(:limit => 10, :order => "created_at DESC").map { |post| ActivityProxy.new(post, post.created_at) }
# and so on with the other objects

Finally you sort the objects

activity.sort_by(&:field)
# => here you have the sorted objects
# and you can iterate them with
activity.each do |proxy|
  proxy.object.id
  # ...
end
Simone Carletti
The activity array appears to be empty, i dont get any errors just an empty array at the end of it
Arcath
Change `+` to `+=`
Simone Carletti
A: 

You have to:

  1. query elements for each model
  2. merge them in a common format
  3. sort and limit

Here is some code:

class Activity < Struct.new(:title, :text, :date); end

limit = 10
activities = []
activities += Post.all(:order => 'created_at DESC', :limit => limit).map do |post|
  Activity.new(post.title, post.summary, post.created_at)
end

activities += Planet.all(:order => 'published_at DESC', :limit => limit).map do |planet|
  Activity.new(planet.title, planet.message, planet.published_at)
end

activities += Message.all(:conditions => ['receiver_id = ?', current_user.id], :order => 'created_at DESC', :limit => limit).map do |message|
  Activity.new(message.title, message.text, message.created_at)
end

# descending sort by 'date' field
sorted_activities = activities.sort_by(&:date).reverse

# 10 most recent elements across all models
@activities = sorted_activities[0..(limit-1)]

Of course, depending on your models, you will have to change which method is used as "title" or "text".

But if you happen to need many of such idioms, you should use Single Table Inheritance as we do in zena (a rails CMS).

Gaspard Bucher
im having a problem with the sorting, it seems to clump all the Posts toegether in order then has the all the Planets together in order instead of mixing them
Arcath
François Beausoleil
Arcath