“合并”多个模型。 创建“最近活动”框

如何合并模型,以便我可以按顺序显示最后10个post,Feed条目和私人消息?

post存储在“Post”模型中,并在“created_at”上排序

Feed条目存储在“Planet”中,并在“published_at”上排序

私人消息存储在“消息”中,需要过滤:

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

并在“created_at”上订购

你必须:

  1. 每个模型的查询元素
  2. 以通用格式合并它们
  3. 排序和限制

这是一些代码:

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

当然,根据您的模型,您必须更改使用哪种方法作为“标题”或“文本”。

但是如果你碰巧需要很多这样的习语,你应该像在zena (rails CMS)中那样使用单表inheritance。

我会使用Proxy类。 该类可以存储ActiveRecord对象引用和用于排序的字段。

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

然后你加载你的对象。

 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 

最后,您对对象进行排序

 activity.sort_by(&:field) # => here you have the sorted objects # and you can iterate them with activity.each do |proxy| proxy.object.id # ... end 

另一种创建Feed的方法是创建一个VIEW,它将两者合并,然后让视图拥有它自己的模型。