2010-05-09 6 views
7

Je voudrais lister tous les postes connectés à une catégorie spécifique et à une salle de classe.Rails 3 trouver tous les articles associés has_many: through

Je:

class Post < ActiveRecord::Base 
    has_many :category_posts 
    has_many :categories, :through => :category_posts 
    has_many :classroom_posts 
    has_many :classrooms, :through => :classroom_posts 
end 

class Category < ActiveRecord::Base 
    has_many :category_posts 
    has_many :posts, :through => :category_posts 
end 

class CategoryPost < ActiveRecord::Base 
    belongs_to :category 
    belongs_to :post 
end 

class Classroom < ActiveRecord::Base 
    has_many :classroom_posts 
    has_many :posts, :through => :classroom_posts 
end 

class ClassroomPost < ActiveRecord::Base 
    belongs_to :classroom 
    belongs_to :post 
end 

Je veux faire quelque chose comme ça

Post.where(["category.id = ? AND classroom.id = ?", params[:category_id], params[:classroom_id]]) 

Il est en effet tâche très simple, mais je ne sais pas ce que je rechercherai (mots-clés) .

C'est le même problème que this, mais dans les rails.

EDIT: J'ai ajouté plus de détails à la question. Cela fonctionne, mais seulement si j'ai les deux params spécifiés. La sorcière n'est pas toujours le cas - je ne sais pas quels params seraient spécifiés.

Post.joins(:categories, :classrooms).where(["categories.id = ? AND classrooms.id = ?", params[:classroom_id], params[:category_id]]) 

Répondre

4
Category.find(params[:category_id]).posts 

Jetez aussi un coup d'œil sur les guides:

+0

Cela fonctionne, merci. Mais que se passe-t-il si j'ai une autre association plusieurs-à-plusieurs (disons Classrooms) à ce poste et je veux trouver à la fois par catégorie et par salle de classe? Quelque chose comme Post.where (["category.id =? ET classroom.id =?", Params [: category_id], params [: classroom_id]]) – Sergey

+0

Que diriez-vous de: Post.where (["category_id =?" , params [: category_id]). où (["classroom_id =?", params [: classroom_id]]) – Chap

+0

@chap Je n'ai pas ces champs dans la table Post. C'est pourquoi je demande.S'il vous plaît lire la question. – Sergey

0

On dirait que vous avez besoin d'un si statment.

if params[:category_id] && params[:classroom_id] 
    Post.joins(:categories, :classrooms).where("classrooms.id" => params[:classroom_id], "categories.id" => params[:category_id]]) 
elsif params[:category_id] 
    Category.find(params[:category_id]).posts 
else 
    Classroom.find(params[:classroom_id]).posts 
end 
2

Je pense que cela devrait fonctionner:

Post.joins(:category_posts, :classroom_posts) 
.where(
["category_posts.category_id = ? 
AND classroom_posts.classroom_id = ?", params[:category_id], params[:classroom_id]]) 

Cela traslate à un SQL comme:

SELECT 
    p.* 
FROM 
    posts AS p 
     INNER JOIN 
    category_posts AS cap ON cap.id = p.category_posts_id 
     INNER JOIN 
    classroom_posts AS clp ON clpid = p.classroom_posts_id 
WHERE 
    cap.category_id = '1' AND clp.classroom_id = '1' 
; 

Quant à savoir si l'utilisation: INCLUDE ou se joint à Post regarder ce answer sur stackoverflow.

4

Voici ce que je ferais dans Rails 3:

En post.rb:

def self.in_category(category_id) 
    if category_id.present? 
    join(:category_posts).where(category_posts: {category_id: category_id}) 
    else 
    self 
    end 
end 

def self.in_classroom(classroom_id) 
    if classroom_id.present? 
    join(:classroom_posts).where(classroom_posts: {classroom_id: category_id}) 
    else 
    self 
    end 
end 

Je ne joignent pas Classroom ou Category car il fait plus de travail pour SGBD et ce n'est pas nécessaire.

Maintenant, vous pouvez faire:

Post.in_category(params[:category_id]).in_classroom(params[:classroom_id]) 

Je ne l'ai pas testé cependant. Donc, n'hésitez pas à demander si nécessaire.

Questions connexes