2010-10-30 2 views
0

D'accord, voici la question la plus délicate que j'ai jamais eu à poser sur StackOverflow.Rails - News Feed

Mon application Web permet de créer un document. Ce document est automatiquement sauvegardé laisse dire quelques secondes.

En attendant, je veux un fil de nouvelles pour que les utilisateurs sachent ce que font leurs amis. J'ai donc créé un modèle d'observateur que after_create crée un élément de type news_feed.

Problème est cet observateur car il va maintenant créer un news_feed sur jamais enregistrer, ce qui est un énorme firehose.

Donc je veux faire en sorte que le feed de news pour ce modèle ne soit injecté que par session ou toutes les X minutes. J'ai donc ajouté une colonne last_feeded_at au modèle.

Le problème est lorsque j'essaie de mettre à jour ce champ dans l'observateur pour marquer qu'il a été alimenté, ce qui déclenche l'observateur, ce qui fait un gâchis de tout.

Quelle est la meilleure façon de gérer cela? Je suis ouvert à toutes les suggestions intelligentes.

Merci

Répondre

0

Je créerais votre objet newsfeed en utilisant ce genre de logique

def find_or_create_feed 
    if session[:news_feed].nil? 
    NewsFeed.new 
    else 
    NewsFeed.find(session[:news_feed]) 
    end 
end 

De cette façon, vous pouvez retourner le même objet NewsFeed pour une session entière. Si vous voulez vous amuser et l'expirer, faites un balayage du tableau news_feeds périodiquement pour supprimer les flux sur un âge donné.

+0

@ Steve, merci, mais où cela vivrait-il? Pouvez-vous donner un peu plus de contexte autour du cas d'utilisation? vraiment excité d'apprendre une façon plus intelligente de faire ce que j'essaie de faire. Mon code devient salissant! merci – AnApprentice

+0

Eh bien, c'est votre application, mais je suppose que vous avez un contrôleur qui, d'après ce que vous décrivez, gère l'interaction de l'utilisateur autour de la création et la modification d'un document. Encore une fois, à partir de votre description, il semblerait que vous vouliez créer un fil de nouvelles lorsque le document est accédé pour la première fois dans une session donnée. Donc, je suppose que je dirais que le frapper dans un before_filter et affecter le résultat à une variable d'instance afin que votre vue peut l'afficher. Ou ... il est possible que vous ayez manqué votre intention pour cette fonctionnalité. –

+0

Le contrôleur ne doit effectuer qu'une action sur un modèle, par ex. enregistrer une mise à jour pour Document. Le modèle Document devrait alors effectuer toutes les actions dépendantes qui existent. – Ariejan

2

Je ne voudrais pas ajouter d'attribut à votre modèle de document pour cela. Vous avez probablement quelque chose comme ça déjà:

class Document 
    has_many :news_feeds, :order => 'created_at DESC' 
end 

Dans votre rappel (dans le modèle de document), il suffit de cocher lorsque le dernier news_feed a été créé:

after_save :create_news_feed, :if => Proc.new { |doc| doc.news_feeds.first.created_at <= 10.minutes.ago } 

Cela n'appeler create_news_feed si le dernier news_feed était créé il y a au moins 10 minutes.

+0

Juste remarqué votre exigence de session. Ajoutez un 'attr_accessor: session_id' à votre modèle Document et stockez cette valeur avec chaque enregistrement new_feed que vous créez. Mettez à jour l'instruction ': if' en conséquence. – Ariejan

+0

L'OP voulait un fil de nouvelles par session. Pourquoi ne pas fonder la création du fil de nouvelles sur la session plutôt que sur l'âge? –

+0

Intéressant, j'essayais de faire tout cela dans l'OBserver pour le garder isolé. – AnApprentice

1

Je suppose que lorsque l'utilisateur termine l'édition, il effectue une sauvegarde finale? Définissez un attr_accessor, draft, qui est envoyé en tant que paramètre du contrôleur lors de la gestion des sauvegardes ajax request.js. Je ne vois pas vraiment le besoin d'un observateur; il suffit de le mettre dans le modèle.

attr_accessor :draft 
after_save :log_unless_draft 

def log_unless_draft 
    unless draft.eql?(true) 
    log_event.new(... 

D'ailleurs, je ne comprends pas pourquoi after_create est même le déclenchement, étant donné ceux-ci ne sont pas new_record? S au-delà de la première sauvegarde.

+0

Pour ajouter un peu plus de couleur. Lorsqu'un utilisateur clique sur Nouvelle note, une note est créée, puis l'utilisateur est redirigé vers la note pour commencer à taper .. Je ne souhaite pas d'élément de fil de nouvelles à ce moment, car le titre de la note n'a pas encore été défini. C'est pourquoi je veux juste le nourrir une fois le titre est noté Sans titre .... – AnApprentice

+0

En outre, il n'y a pas de sauvegarde finale, c'est plus comme Google Docs, la note est enregistrée automatiquement sur le serveur (DEF UPDATE) sur une minuterie et basé sur l'activité de l'utilisateur. Ce sont ces sauvegardes qui inondent le flux et que je veux gérer. Cela a-t-il du sens? – AnApprentice

+0

Donne un sens à l'inondation même si google docs dispose d'un bouton de sauvegarde (final); Personnellement, je pense que ce serait une mauvaise conception de l'interface de ne pas. Les utilisateurs s'attendent à enregistrer quand ils ont terminé et ce serait le moment idéal pour se connecter au flux. – mark