28 votes

Comment charger des objets avec une jointure personnalisée dans des rails?

Arrière-plan

Rails normale désireux de chargement des collections fonctionne comme ceci:

Person.find(:all, :include=>:companies)

Cela génère une certaine sql qui ne

LEFT OUTER JOIN companies ON people.company_id = companies.id

Question

Cependant, j'ai besoin d'un custom rejoindre (ce qui peut aussi survenir si j'ai été en utilisant find_by_sql) donc je ne peux pas utiliser de la vanille en :include => :companies

La coutume se joindre/sql va me faire de toutes les données dont j'ai besoin, mais comment puis-je savoir activerecord qu'il appartient à l'associated Company objets plutôt que d'être simplement un tas de lignes supplémentaires?

Mise à jour

J'ai besoin de mettre des conditions supplémentaires à la jointure. Quelque chose comme ceci:

SELECT blah blah blah
LEFT OUTER JOIN companies ON people.company_id = companies.id AND people.magical_flag IS NULL 
<Several other joins>
WHERE blahblahblah

7voto

Toby Hede Points 22128

Pouvez-vous ne pas ajouter les conditions de jointure à l'aide de ActiveRecord?

Par exemple, j'ai une assez complexe requête à l'aide de plusieurs dépendante de dossiers et il fonctionne très bien en combinant les conditions et les directives d'

Contractors.find(
  :all, 
  :include => {:council_areas => :suburbs},
  :conditions => ["suburbs.postcode = ?", customer.postcode]                 
)

En supposant que:

  1. Les entrepreneurs have_many CouncilAreas
  2. CouncilAreas have_many Banlieue

Cette jointure renvoie les Entrepreneurs dans la banlieue identifiés par le client.le code postal.

La requête générée ressemble:

SELECT contractors.*, council_areas.*, suburbs.*
FROM `contractors` 
LEFT OUTER JOIN `contractors_council_areas` ON `contractors_council_areas`.contractor_id = `contractors`.id 
LEFT OUTER JOIN `council_areas` ON `council_areas`.id = `contractors_council_areas`.council_area_id 
LEFT OUTER JOIN `council_areas_suburbs` ON `council_areas_suburbs`.council_area_id = `council_areas`.id 
LEFT OUTER JOIN `suburbs` ON `suburbs`.id = `council_areas_suburbs`.suburb_id WHERE (suburbs.postcode = '5000')

(Note: j'ai édité la liste des colonnes pour des raisons de concision).

3voto

Jeremiah Peschka Points 4756

Vous pouvez utiliser quelque chose comme ce qui suit pour obtenir la magie syntaxique de jointure externe gauche appropriée.

 Person.reflect_on_association(:companies).options[:conditions] = 'people.magical_flag IS NULL'
 

2voto

Tomasz Wałkuski Points 590

Je ne suis pas sûr que ce soit ce que vous voulez (je ne suis pas sûr à 100% d'avoir compris votre question et ce que vous voulez accomplir) mais:

Qu'en est-il de fournir à la fois :joins et :includes ?

Person.find( :all, :joins => 'LEFT OUTER JOIN companies ON people.company_id = companies.id AND _pass_custom_conditions_here_', :includes => :companies )

Ou façon AR3:

Person.includes(:companies).joins('LEFT OUTER JOIN companies ON people.company_id = companies.id AND _pass_custom_conditions_here_')

1voto

user19898 Points 21

Pouvez-vous élaborer un peu plus sur exactement ce que vous essayez d'accomplir avec cette requête?

Jetez aussi un oeil à l' :joint option pour trouver. Il vous permet de spécifier comment vous voulez que les tables jointes. texte du lien

Et méfiez-vous lors de l'utilisation :comprendre, le comportement change un peu dans les Rails 2.1 et peut causer certains problèmes lorsqu'il est utilisé conjointement avec un :conditions de l'option qui fait référence à une table. texte du lien et le texte du lien sont deux articles de Pivot que la mention de cette chasse aux sorcières.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X