2011-06-14 17 views
5

Deseo crear un feed de actividad a partir de artículos recientes y comentarios en mi aplicación de rieles. Son dos tipos diferentes de activerecord (sus estructuras de tabla son diferentes).Crear un avance de noticias en Rails 3

Idealmente, podría crear una serie mixta de artículos y comentarios y luego mostrarlos en orden cronológico inverso.

Entonces, puedo averiguar cómo obtener una variedad de artículos y comentarios y luego combinarlos y ordenarlos por created_at, pero estoy bastante seguro de que eso no funcionará tan pronto como empiece a usar la paginación también. .

¿Hay alguna manera de crear un alcance que cree una matriz mixta?

Uno de los otros problemas para mí, es que podrían ser todos los artículos y podrían ser todos los comentarios o alguna combinación intermedia. Así que no puedo decir que tomaré los últimos 15 artículos y los 15 últimos comentarios.

¿Alguna idea sobre cómo solucionar esto?

+0

esto podría ayudarle http : // mickeyben.com/2010/05/23/creating-an-activity-feed-with-rails, -ar-and-observers.html – corroded

Respuesta

7

cuando he done this before He conseguido que por tener un modelo desnormalizaremos UserActivity o similar con una asociación polimórfica belongs_to a un ActivitySource - que puede ser cualquiera de los tipos de contenido que desea mostrar (mensajes, comentarios, votos, Me gusta, lo que sea ...).

Luego, cuando se crea cualquiera de las entidades para mostrar, tiene un Observer que dispara y crea una fila en la tabla UserActivity con un enlace al registro.

continuación para mostrar la lista, que acaba de consulta en UserActivity pedido por created_at descendente, y luego navegar a través de la asociación activity_source polimórficos para obtener los datos de contenido. Sin embargo, necesitará algunas funciones inteligentes en sus plantillas de vista para presentar comentarios y publicaciones, y cualquier otra cosa diferente.

E.g. algo así como ...

user_activity.rb:

class UserActivity < ActiveRecord::Base 
    belongs_to :activity_source, :polymorphic => true 

    # awesomeness continues here... 
end 

comment.rb (post/lo que sea)

class Comment < ActiveRecord::Base 
    # comment awesomeness here... 
end 

activity_source_observer.rb

class ActivitySourceObserver < ActiveRecord::Observer 

    observe :comment, :post 

    def after_create(activity_source) 
    UserActivity.create!(
     :user => activity_source.user, 
     :activity_source_id => activity_source.id, 
     :activity_source_type => activity_source.class.to_s, 
     :created_at => activity_source.created_at, 
     :updated_at => activity_source.updated_at) 
    end 

    def before_destroy(activity_source) 
    UserActivity.destroy_all(:activity_source_id => activity_source.id) 
    end 

end 
+4

Un problema con esto es que cuando se destruye un modelo, estás destruyendo sus actividades asociadas en lugar de creando una actividad para la destrucción Imagine una alimentación de actividad como la de Github; cuando crea un repositorio, eso se publica en su feed. Cuando elimina un repositorio, su feed muestra que ha eliminado un repositorio. – bratsche

+0

@bratsche, siento que es un caso extremo. esto es algo intrínsecamente complicado/complicado de construir, para mi propósito, si alguien borra un registro, realmente QUIERO que se eliminen los elementos del feed. – wuliwong

0

Eche un vistazo a this railscast.

A continuación, puede paginar 15 artículos y en app/views/articles/index se puede hacer algo como esto:

- @articles.each do |article| 
    %tr 
    %td= article.body 
    %tr 
    %td= nested_comments article.comment.descendants.arrange(:order => :created_at, :limit => 15) 

Esto supone las siguientes relaciones:

#app/models/article.rb 
has_one :comment # dummy root comment 

#app/models/comment.rb 
belongs_to :article 
has_ancestry 

Y añadir comentarios a un artículo de la siguiente manera:

root_comment = @article.build_comment 
root_comment.save 
new_comment = root_comment.children.new 
# add reply to new_comment 
new_reply = new_comment.children.new 

Y así sucesivamente.