2009-06-12 4 views
0

J'ai une application de rails utilisant le plugin acts_as_rateable.Comment trouver des modèles non notés avec acts_as_rateable

Je suis bloqué sur la façon de récupérer des modèles non notés en utilisant ce plugin - mais il s'agit plus d'une question générale sur les rails/SQL que spécifique à ce plugin.

Agit comme ajoute ce qui suit rateable au schéma:

create_table "ratings", :force => true do |t| 
    t.integer "rating",      :default => 0 
    t.string "rateable_type", :limit => 15, :default => "", :null => false 
    t.integer "rateable_id",     :default => 0, :null => false 
    t.integer "user_id",      :default => 0, :null => false 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    add_index "ratings", ["user_id"], :name => "fk_ratings_user" 

Et mes modèles ont aussi noté une colonne d'identification de l'utilisateur. J'aimerais pouvoir récupérer toutes les instances d'un modèle particulier qui n'ont pas été évaluées du tout, ainsi que toutes les instances qui n'ont pas été évaluées par quelqu'un d'autre que le créateur du modèle, par ex. voici un modèle:

class Review < ActiveRecord::Base 
    acts_as_rateable 

    belongs_to :user 
    ... 
end 

Je veux quelque chose comme le pseudo-code suivant

Review.find(:all, :conditions=>"not rated by anyone") 
Review.find(:all, :conditions=>"not rated by anyone except review.user") 

Cependant, je ne peux pas comprendre le SQL pour le faire, ni la magie des rails pour générer ce SQL: - Mise à jour: cette requête semble trouver tous les modèles évalués par quelqu'un d'autre que l'utilisateur propriétaire du modèle. Donc je pense que j'ai juste besoin d'inverser ça d'une manière ou d'une autre.

Review.find(:all, 
    :joins=>'left join ratings on reviews.id=ratings.rateable_id && ratings.rateable_type="Review"', 
    :conditions=>'reviews.user_id <> ratings.user_id', 
    :group=>'reviews.id') 
+0

Do modèles non notés ont une cote de zéro? –

+0

Oui, ils le font, du moins lorsqu'ils utilisent l'interface rails - c'est-à-dire Review.find (1).rating == 0 s'il n'y a pas de classement pour ce modèle – frankodwyer

Répondre

1

Les étendues nommées sont la solution idéale pour ce problème. J'ajouterais deux portées nommées à votre modèle Review. Quelque chose comme:

class Review < ActiveRecord::Base 
    acts_as_rateable 

    belongs_to :user 

    named_scope :not_rated, :conditions => { :rating => 0 } 
    named_scope :not_rated_by_others, 
       :conditions => ["user != ? AND rating == 0", self.user] 
end 

Ensuite, vous pouvez faire:

@not_rated = Review.not_rated 
@not_rated_by_others = Review.not_rated_by_others 

Il y a un Railscast that explains named scopes.


EDIT: deuxième tentative

droit, nous allons faire une autre! Un des problèmes est qu'il y a plusieurs plugins acts_as_rateable là-bas. J'ai testé en utilisant this one sur RubyForge.

class Review < ActiveRecord::Base 
    belongs_to :user 

    acts_as_rateable 

    named_scope :not_rated, :select => 'reviews.*', 
       :joins => 'left join ratings on reviews.id = ratings.rateable_id', 
       :conditions => 'ratings.rateable_id is null' 

    named_scope :not_rated_by_others, lambda { |user| { :select => 'reviews.*', 
       :joins => 'left join ratings on reviews.id = ratings.rateable_id', 
       :conditions => ['ratings.user_id != ? and ratings.rateable_id is null', 
       user] }} 
end 

Utilisez comme ceci:

frank = User.find_by_name('frank') 
@not_rated = Review.not_rated 
@not_rated_by_others = Review.not_rated_by_others(frank) 
+0

J'aime l'idée de named_scope, mais malheureusement la requête elle-même ne fonctionne pas car il n'y a pas de colonne 'rating', c'est quelque chose calculé par le plugin rating. Ainsi, dans la console Review.find (1) .rating fonctionne mais pas en SQL. De même Review.find (1) .ratings == [] dans la console. – frankodwyer

+0

Malheureusement, je n'ai pas eu l'occasion de le tester. Je vais voir si je peux jeter un coup d'oeil ce soir. –

+1

vous devez inclure le rateable_type = @@ whatever_model_type dans votre déclaration de jointure, car la table de classement est polymorphe, donc si vous avez des évaluations sur d'autres choses, il retournera d'autres classes dans votre jeu de résultats – ErsatzRyan

0

J'ai un bout de chemin en utilisant une requête comme ceci:

Review.find(:all, 
:joins=>'left outer join ratings on reviews.id=ratings.rateable_id && ratings.rateable_type="Review"', 
    :conditions=>'ratings.rating is NULL') 

Cela ressemble à elle retourne tous les modèles d'examen sans note du tout.

Et je pense que celui-ci travaille à trouver tous les modèles d'examen qui ne sont pas évalués par l'utilisateur qui a créé la revue:

Review.find(:all, 
    :joins=>'left outer join ratings on reviews.id=ratings.rateable_id && ratings.rateable_type="Review" && ratings.user_id <> reviews.user_id', 
    :conditions=>'ratings.rating is NULL') 
Questions connexes