2010-12-14 92 views
0

Je suis coincé avec cela pendant quelques heures. Ce pourrait être une solution rapide mais mon cerveau est surchauffé maintenant. Ok c'est ici.Comment sélectionner un enregistrement spécifique parmi les relations Plusieurs-à-plusieurs qui ne contient pas d'élément spécifique dans Rails 2?

J'ai des modèles Session et SessionType qui ont des relations plusieurs-à-plusieurs les uns avec les autres comme suit.

class Session < ActiveRecord::Base 
    ... 
    has_and_belongs_to_many :session_types 
    ... 
end 

class SessionType < ActiveRecord::Base 
    ... 
    has_and_belongs_to_many :sessions 
    ... 
end 

Ce que je veux est d'obtenir une session qui ne contient pas de session_type spécifique, par exemple.,

Session.find(:all, :joins => [:session_types], :conditions => ["session_types.id <> 44"]) 

Il ne fonctionne pas pour moi depuis que la requête ci-dessus me donne encore la sessions qui ont session_types.id "44" dans plusieurs de ses associations en raison de la nature des relations plusieurs-à-plusieurs.

Le code mysql suivant ne fonctionne pas aussi bien.

select sessions.* from sessions 
INNER JOIN `session_types_sessions` ON `session_types_sessions`.session_id = `sessions`.id 
WHERE ( session_types_sessions.session_type_id NOT IN (44)) 
GROUP BY sessions.id 

Toute aide sera appréciée.

Merci.

Répondre

1

d'abord sélectionner les sessions qui sont de type 44:

session_types_44 = Session.find(:all, :joins => :session_types, 
    :conditions => { :"session_types.id" => 44 }).uniq 

et sélectionnez les sessions qui ne tombent pas dans ce qui précède:

sessions_without_type_44 = Session.find(:all, 
    :conditions => "id NOT IN (#{session_types_44.join(",")})") 

Vous besoin d'être prudent avec cela car si session_types_44 est tableau vide, vous obtiendrez une erreur SQL.

Et pour répondre à votre deuxième question:

savez-vous comment je pourrais changer le SQL pour filtrer comme « Donne-moi des séances qui ont session_type_id « 43 », mais ils ne doivent pas avoir « 44 »

Prenez le résultat de sessions_without_type_44 et de l'utiliser d'abord sélectionner sessionType avec 43 et par association toutes les sessions se qui appartiennent à ce sessionType et leurs ids sont dans le sessions_without_type_44.

SessionType.find(43).sessions.all(:conditions => { 
    :id => sessions_without_type_44 }) 
+0

Oui cela fonctionne très bien avec un peu de changement de syntaxe car j'ai une erreur de syntaxe autour de la jointure. session_types_44 = Session.find (: all,: jointures =>: session_types,: conditions => {: "session_types.id" => 44}). uniq Session.find (: all,: conditions => ["ID NOT IN (?) ", session_types_44.collect {| s | s.id}]) –

1

Essayez ceci:

SELECT sessions.* 
FROM sessions 
LEFT JOIN session_types_sessions ON session_types_sessions.session_id = sessions.id AND session_types_sessions.session_type_id = 44 
WHERE session_types_sessions.session_id IS NULL 
+0

Très bien. Fonctionne en SQL. Je dois trouver un moyen d'intégrer Rails maintenant. –

+0

Que diriez-vous de 'find_by_sql'? Si vous utilisez Rails 3, il devrait y avoir un moyen facile de le faire dans AREL. – Matt

+0

Ok, je devrais être capable de ça. Juste pendant que vous pouvez aider, savez-vous comment je pourrais changer le SQL pour filtrer comme "get me sessions qui ont session_type_id '43', mais ils ne doivent pas avoir '44'". Merci. –

0

Essayez ceci:

Session.all(
    :include => :session_types, 
    :conditions => ["session_types.id IS NOT NULL AND session_types.id != ?", 44]) 
) 

L'option include utilise LEFT JOIN donc cette requête fonctionnera.