2011-10-20 3 views

Répondre

6

Utilisez un astuce SQL classique: left join puis sélectionnez les lignes où le second ID est nul.

Article. 
    joins(%Q{LEFT JOIN taggings ON taggings.taggable_id=articles.id AND taggings.taggable_type='Article'}). 
    where('taggings.id IS NULL') 
+0

à mon humble avis ce sentir aki et non comme des rails .. – daniel

+0

@ Daniel, il n'y a pas agréable rails façon de travailler avec de jointures complexes. Autre que cela, voir http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html –

+0

Oui, je suis d'accord que 'Article.tagged_with (Tag.all.map (&: to_s),: exclude => true) 'est plus Rails moyen. Mais j'utilise Rails 2.3 et je veux l'utiliser comme un named_scope donc c'est le seul moyen ... – petRUShka

3

Selon the source pour les actes-que-tagable sur, vous pouvez utiliser l'option :exclude:

## 
# Return a scope of objects that are tagged with the specified tags. 
# 
# @param tags The tags that we want to query for 
# @param [Hash] options A hash of options to alter you query: 
#      * <tt>:exclude</tt> - if set to true, return objects that are *NOT* tagged with the specified tags 
#      * <tt>:any</tt> - if set to true, return objects that are tagged with *ANY* of the specified tags 
#      * <tt>:match_all</tt> - if set to true, return objects that are *ONLY* tagged with the specified tags 
#      * <tt>:owned_by</tt> - return objects that are *ONLY* owned by the owner 

Donc, dans votre exemple, juste faire:

Article.tagged_with("tag", :exclude => true) 

EDIT: Je viens de réaliser que vous avez demandé des articles sans étiquettes, auquel cas, vous devrez fournir la liste de tous vos tags à la méthode:

Article.tagged_with(Tag.all.map(&:to_s), :exclude => true) 
0

Vous pouvez simplement utiliser la fonction de sélection. Je suppose que la solution SQL est beaucoup plus efficace, mais cela ressemble peu plus agréable:

Artical.all.select{|a| a.tags.count == 0 } 
1

la façon dont SQL ressemble hackie et carte à l'aide va être lent à coup sûr.

Ici vous pouvez obtenir avec deux requêtes (rails 4):

ids = Taggings.where(taggable_type: "Article").collect(&:taggable_id).uniq 
Article.where.not(id: ids) 
Questions connexes