“merging” multiple models. To create a “recent activity” box

匿名 (未验证) 提交于 2019-12-03 02:45:02

问题:

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"

回答1:

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).



回答2:

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


回答3:

Another method for creating feeds is to create a VIEW that combines the two then let the view have it's own model.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!