2010-08-03 7 views
6

En Rails3 il semble y avoir un problème lorsque enchaînant deux champs d'application (ActiveRelations) qui ont chacun un autre comprennent:problème: activerecord (rails3), champs d'application enchaînant avec comprend

Tenir compte de ces deux champs d'application, tous deux fonctionnent bien sur leur propre:

champ d'application,:

scope :global_only, lambda { |user| 
includes(:country) 
.where("countries.area_id <> ?", user.area) } 

Work.global_only (utilisateur) => (liste de coupe des champs de SQL pour la lisibilité)

SELECT * FROM "works" LEFT OUTER JOIN "countries" ON "countries"."id" = "works"."country_id" WHERE (countries.area_id <> 3) 

Maintenant, le deuxième champ:

scope :not_belonging_to, lambda { |user| 
includes(:participants) 
.where("participants.user_id <> ? or participants.user_id is null", user) } 

Work.not_belonging_to (utilisateur) => (liste de coupe des champs de SQL pour la lisibilité)

SELECT * FROM "works" LEFT OUTER JOIN "participants" ON "participants"."work_id" = "works"."id" WHERE (participants.user_id <> 6 or participants.user_id is null) 

Ainsi, les deux ceux qui travaillent correctement individuellement.

Maintenant, les Enchaînez:

Work.global_only (utilisateur) .not_belonging_to (utilisateur)

SQL:

SELECT (list of fields) FROM "works" LEFT OUTER JOIN "countries" ON "countries"."id" = "works"."country_id" WHERE (participants.user_id <> 6 or participants.user_id is null) AND (countries.area_id <> 3) 

Comme vous pouvez le voir, la jonction de la deuxième portée est complètement ignoré. Le SQL échoue donc sur 'no such column' participants.user_id '. Si j'enchaîne les étendues dans l'ordre inverse, la jointure 'participants' sera présente et la jointure 'pays' sera perdue. C'est toujours la deuxième jointure qui est perdue, semble-t-il.

ce que ça ressemble un bug avec ActiveRecord, ou je fais quelque chose de mal, ou est-ce une « fonction » :-)

(PS. Oui, je sais, je peux créer un champ qui se joint à la fois je vais le faire déjà, mais j'essayais de faire de plus petites étendues que ce qui peut être enchaîné de différentes manières, ce qui est censé être l'avantage de activer l'enregistrement sur SQL direct.)

+2

Il se trouve que c'est un bogue; être patché pour la prochaine version de Rails3. –

+0

yup, en ce moment, il ne comprend que 1 fois, donc si vous voulez contourner le problème, faites une nouvelle portée qui comprend à la fois ... comprend (: pays,: participant) ... oups ... juste réalisé thats buggy aussi * soupir * ... désolé – Ingo

Répondre

5

En règle générale, utilisez :includes pour le chargement rapide et :joins pour les conditions. Dans la seconde portée, le joint SQL doit être écrit manuellement car une jointure à gauche est requise.

Cela dit, essayez ceci:

scope :global_only, lambda { |user| 
    joins(:country). 
    where(["countries.area_id != ?", user.area]) 
} 

scope :not_belonging_to, lambda { |user| 
    joins("left join participants on participants = #{user.id}"). 
    where("participants.id is null") 
} 

Work.global_only(user).not_belonging_to(user)