2010-10-23 5 views
2

J'ai des utilisateurs, des messages et des commentaires. L'utilisateur peut publier un seul commentaire à chaque publication.Récupérer tous les messages où un utilisateur donné a fait un commentaire, Ruby on Rails

class User < ActiveRecord::Base 
    has_many :posts 
    has_many :comments 
end 

class Post < ActiveRecord::Base 
    has_many :comments 
    belongs_to :user 
end 

class Comment < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :post 
end 

Sur userpage (http://host/users/1 par exemple) Je veux montrer tous les messages où l'utilisateur donné a commenté. Chaque message aura alors tous les autres commentaires.

Je peux faire quelque chose comme ça dans mon contrôleur de l'utilisateur:

def show 
    @user = User.find(params[:user_id]) 
    @posts = [] 
    user.comments.each {|comment| @posts << comment.post} 
end 

De cette façon, je trouverai l'utilisateur, puis tous ses commentaires, puis poste correspondant à chaque commentaire, puis (à mon avis) pour chaque Je publierai post.comments. Je suis totalement nouveau dans Rails, donc je peux le faire =) Mais je pense que c'est en quelque sorte mauvais et il y a une meilleure façon de le faire, peut-être que je devrais utiliser des scopes ou named_scopes (je ne sais pas encore effrayant).

Alors pouvez-vous me montrer la bonne direction ici?

Répondre

5

Vous pouvez définir une association qui récupère tous les messages avec des commentaires dans une seule requête. Le conserver dans le modèle réduit la complexité de vos contrôleurs, vous permet de réutiliser l'association et facilite le test unitaire.

class User < ActiveRecord::Base 
    has_many :posts_with_comments, :through => :comments, :source => :post 
    # ... 
end 

:through est une option pour has_many spécifier une table de jointure à travers laquelle pour exécuter la requête. Nous devons spécifier le :source car Rails ne serait pas en mesure de déduire la source de :post_with_comments. Enfin, mettez à jour votre contrôleur pour utiliser l'association.

def show 
    @user = User.find(params[:user_id]) 
    @posts = @user.posts_with_comments 
end 

Pour mieux comprendre :through et :source un coup d'oeil à la documentation.

+0

Je dois admettre que je me suis perdu la première fois que j'ai lu ceci, parce que mon esprit était toujours bloqué sur une relation 'user -> post -> comment'. Mais, après l'avoir examiné quelques fois, j'ai fait le pivot du modèle mental 'utilisateur -> commentaire -> poste'. Le commentaire ressemble à un modèle de correspondance classique de plusieurs à plusieurs, et tout cela semble si simple! –

+0

Wow! Cela fonctionne très bien. Et c'était plus facile que je ne le pensais. Je vous remercie. – fetsh

+0

@Edward Vous êtes sur l'ongle. 'has_many: through =>' est plus ou moins le même que 'has_and_belongs_to_many' excepté' has_many: through => 'vous permet de travailler sur l'association de jointure. C'est un cas d'utilisation courant, bien que cela fonctionne parfaitement pour @ilzoff. –

0

Lorsque vous avez l'utilisateur, vous avez les associations à ses messages et chaque poste a ses commentaires. Vous pouvez écrire: (je ne sais pas les noms de vos champs de table, donc je peux nommer le texte du texte)

# In Controller 
@user = User.find(params[:user_id]).include([:posts, :comments]) 

# In View 
@user.posts.each do |post| 
    post.text 
    # Comments to the Post 
    post.comments.each do |comment| 
    comment.text 
    end 
end 

Je ne l'ai pas testé le code, donc il pourrait y avoir des erreurs.

+0

Ce n'est pas exactement ce que je voulais. Je n'ai pas besoin de tous les messages des utilisateurs, mais tous les messages à travers les commentaires des utilisateurs. Vous pouvez voir, la réponse de Tate Johnson, ça marche pour moi. – fetsh

Questions connexes