2010-01-20 1 views
10

Come si uniscono i modelli in modo che sia possibile visualizzare gli ultimi 10 post, voci di feed e messaggi privati ​​in ordine?"unione" di più modelli. Per creare una casella "attività recenti"

messaggi vengono memorizzati nel modello "Post" e ordinati su "created_at"

Feed Entries sono memorizzati in "Planet" e ordinati su "published_at"

messaggi privati ​​vengono memorizzati in "Messaggio" e devono essere filtrati con:

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

e ha ordinato il "created_at"

risposta

11

Dovete:

  1. elementi di query per ogni modello
  2. loro unione in un formato comune
  3. specie e limitare

Ecco il codice:

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

Naturalmente, a seconda delle vostre modelli, si dovrà cambiare il metodo utilizzato come "titolo" o "testo".

Ma se ti capita di aver bisogno di molti di questi idiomi, dovresti utilizzare l'ereditarietà di tabelle singole come facciamo in zena (un CMS di rotaie).

+0

ho problemi con l'ordinamento, sembra raggruppare tutto Dopo aver ordinato in ordine, allora ha riunito tutti i pianeti in ordine invece di mischiarli. – Arcath

+0

Usa #sort_by invece: activities.sort_by (&: created_at) .reverse [0, limit] –

+0

grazie, deve essere '@ activites = activities .sort_by (&: date) .reverse [0, limit] 'using: date in modo che sia il campo nella classe Attività – Arcath

11

vorrei usare una classe proxy. La classe può memorizzare il riferimento all'oggetto ActiveRecord e il campo per l'ordinamento.

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

Quindi carichi gli oggetti.

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 

Infine si ordinano gli oggetti

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

L'array di attività sembra essere vuoto, non ottengo alcun errore solo un array vuoto alla fine di esso – Arcath

+0

Cambia '+' a '+ =' –

1

Un altro metodo per la creazione di feed è creare una VISTA che combina i due, quindi lasciare che la vista abbia il proprio modello.

+1

Per una spiegazione, vedere: https: // dan. chak.org/enterprise-rails/chapter-11-view-backed-models/ –