2010-06-06 3 views
2

J'ai une table des commentaires et une table des messages, où un message a beaucoup de commentaires et un commentaire appartient à un poste (c'est-à-dire qu'il a un post_id dans le tableau).Rails ActiveRecord: Sélectionnez les messages SANS les commentaires

Comment puis-je sélectionner efficacement les dix derniers messages qui n'ont PAS de commentaires? Je ne peux pas sembler accomplir ceci sans d'abord sélectionner tous les poteaux et vérifier chacun pour un compte de 0 commentaires.

Merci d'avance pour toute aide.

-Nathan

Répondre

3

Vous pouvez ajouter un counter cache au modèle Comment et un couple de named scopes au modèle Post. Quelque chose comme:

class Post < ActiveRecord::Base 
    has_many :comments 

    named_scope :recent, :limit => 10, :order => 'created_at DESC' 
    named_scope :uncommented, :conditions => { :comments_count => 0 } 
end 

class Comment < ActiveRecord::Base 
    belongs_to :post, :counter_cache => true 
end 

Si vous utilisez Rails 3, alors la syntaxe de champ le nom est un peu différent:

class Post < ActiveRecord::Base 
    has_many :comments 

    scope :recent, limit(10).order('posts.created_at DESC') 
    scope :uncommented, where(:comments_count => 0) 
end 

vous pouvez maintenant trouver les messages sans commentaires en enchaînant les champs nommés ensemble:

@uncommented = Post.recent.uncommented 

Si vous voulez récupérer tous les messages sans commentaires (non seulement les dix postes les plus récents), il serait:

@uncommented = Post.uncommented 

— Vous avez peut-être remarqué que dans les rails 3 exemple I inclus le nom de la table posts dans le périmètre :recent. C'est une bonne pratique à suivre pour éviter les noms de colonne ambigus dans les requêtes SQL si deux tables ont le même nom de colonne. This Railscast explique plus.

0

Vous devez ajouter une condition en quelque sorte comme ceci:

:conditions => '(SELECT count(*) FROM comments WHERE post_id = #{id}) = 0' 

Je ne suis pas un expert en SQL alors peut-être il y a quelque chose comme un mot-clé EMPTY ou ainsi.

+0

d'ailleurs vous devriez avoir des guillemets doubles pour que # {id} soit substitué –

+2

Mieux vaut ne pas le faire de toute façon car cela pourrait ouvrir votre code à l'injection SQL.Pour ce faire: conditions => ['(SELECT ... O WH post_id =?) = 0', id] – hurikhan77

+0

@ hurikhan77: Vous avez raison. Je me référais à une relation ActiveRecord où il serait bon de faire comme je l'ai écrit. – fphilipe

8

Vous pouvez faire

Post.find(:all, :include => :comments, :conditions => "comments.id is null", :limit => 10, :order => "created_at desc") 
1

Ajouter une colonne comments_count à votre table de messages et laisser la mise à jour de la migration des compteurs. A partir de maintenant Rails mettra automatiquement à jour votre compteur si vous fournissez :counter_cache => true sur l'association. Il est très facile de sélectionner les 10 derniers messages maintenant:

Post.find_all_by_comments_count 0, :order => 'created_at DESC', :limit => 10 

lien Documentation: http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M001318

0

Post.includes (: commentaires) .où ("commentaires .id is null ")

Questions connexes