2012-01-15 6 views
1

J'essaie de sélectionner plusieurs colonnes après une jointure. Je ne pouvais pas trouver un moyen de le faire en utilisant ActiveRecord sans écrire SQL entre guillemets dans la requête (chose que je voudrais éviter)Joindre et sélectionner plusieurs colonnes

Explorer Arel, j'ai trouvé que je pouvais sélectionner plusieurs colonnes en utilisant "projet" , cependant je ne suis pas sûr si je devrais utiliser Arel directement ou s'il y avait un moyen d'atteindre la même chose avec AR.

C'est le code Arel:

l = Location.arel_table 
r = Region.arel_table 

postcode_name_with_region_code = l.where(l[:id].eq(location_id)).join(r).on(l[:region_id].eq(r[:id])).project(l[:postcode_name], r[:code]) 

Après l'exécution de cette requête, je voudrais revenir quelque chose le long des lignes de: (pseudo-code)

"#{:postcode_name}, #{:code}" 
  1. Existe-t-il un moyen d'obtenir la même requête en utilisant AR?
  2. Si je m'en tiens à Arel, comment puis-je obtenir les valeurs de la classe SelectManager, la requête ci-dessus retourne.

Merci à l'avance,

Répondre

0

Utilisation AR, sans écrire de SQL et en supposant que vos modèles et associations sont:

modèles/region.rb

class Region < ActiveRecord::Base 
    has_many :locations 
end 

modèle/location.rb

class Location < ActiveRecord::Base 
    belongs_to :region 
end 

Vous pouvez certainement faire:

postcode_name_with_region_code = Location.where(:id=>location_id).includes(:region).collect{|l| "#{l.postcode_name}, #{l.region.code}"} 

Cela fera la requête et puis utilisez Ruby pour formater votre résultat (notez qu'il retourne un tableau puisque je suppose qu'il pourrait y avoir plusieurs enregistrements retournés). Si vous ne voulez qu'un élément du tableau, vous pouvez utiliser la méthode array.first pour le référencer.

Vous pouvez également la charge de l'association et désireux de construire votre chaîne à partir du résultat:

my_loc = Location.find(location_id, :include=>:region) 

postcode_name_with_region_code = "#{my_loc.postcode_name}, #{my_loc.region.code}" 
+0

Merci Mike pour vous répondre. Cela amène une autre question, en termes de performance, qui ne serait pas plus efficace pour faire des jointures par opposition aux inclusions? Il peut ne pas être un succès significatif de la performance avec cette requête, mais je l'ai vu interroger la base de données deux fois lors de l'utilisation d'includes. – Digger

+0

Les jointures ne vous achèteront vraiment rien dans ce cas. Si vous voulez essayer, remplacez .includes (...) par .joins ("JOIN locations.region_id ON regions.id"). La deuxième requête est le résultat de l'interrogation collect pour le code de la région. J'ai ajouté une solution qui tire parti du chargement de l'association par l'AR si vous voulez essayer aussi. – miked

+0

Merci, je vais essayer. Après un peu de jeu avec AR, voici la requête que j'ai commencé à utiliser: 'Location.joins (: region) .where (: id => location_id) .select ('locations.nom_colode, regions.code') .map {| l | "# {l.numéro_de_module}, # {l.code}"} ' – Digger

0
predicate = Location.where(:id=>location_id).includes(:region) 
predicate.ast.cores.first.projections.clear 
predicate.project(Location.arel_table[:postcode_name], Region.arel_table[:code]) 
Questions connexes