37 votes

Rails 3 - sélectionner avec Include ?

Voici un select imbriqué avec include :

@items = Item.where("complete = ?", true).includes( :manufacturer, {:order=>[:supplier, :agent] })

Il s'agit d'une requête exigeante car elle extrait des milliers de lignes de données de toutes les tables mentionnées ci-dessus.

Comment puis-je faire en sorte que la requête ne sélectionne que des champs spécifiques ?

  • nom de l'utilisateur, date de création de l'utilisateur
  • commande.created_at
  • nom du fournisseur
  • agent.nom
  • fabricant.nom

32voto

Patrick Klingemann Points 4560

Il existe une méthode select dans ARel, mais vous devez utiliser les noms de table corrects (c'est-à-dire au pluriel et attention si vous avez des modèles polymorphes ou si vous utilisez set_table_name ou une autre pratique non standard similaire).

@items = Item.
  select('users.name', 'users.created_at', 'orders.created_at', 'suppliers.name', 'agents.name', 'manufacturers.name').
  where(:users => { :fulfilled => true }).
  includes(:orders => [:supplier, :agent], :manufacturer)

"Nous pouvons utiliser select avec les jointures mais pas avec les inclusions" - @Bhavesh_A_P

Note :

Comme l'a souligné @Bhavesh_A_P ci-dessus, select con includes ne produit pas un comportement cohérent. Il semble que si l'association incluse ne renvoie aucun résultat, select fonctionnera correctement, s'il renvoie des résultats, l'instruction select n'aura aucun effet. En fait, elle sera complètement ignorée, de sorte que votre instruction select pourrait faire référence à des noms de tables invalides sans qu'aucune erreur ne soit produite. select con joins produira un comportement cohérent.

17voto

Bhaveshkumar Points 123

En fait, on ne peut pas utiliser select avec includes. On ne peut l'utiliser qu'avec des jointures.

5voto

Byofuel Points 56

Le problème n'est pas résolu en incluant un appel à la méthode "select" dans la chaîne. Dans un ActiveRecord::Relation similaire que nous avons construit, l'appel à 'includes' semble remplacer tout appel à 'select'.

scope :active, where("hired_on < ? AND (separated_on > ? OR separated_on IS NULL)", Time.now, Time.now )

scope :with_role, lambda {|roles| includes(:team_member_roles).where(:team_member_roles => {:role => roles } ) }

scope :with_site_code, lambda {|site_codes| includes(:team_member_sites).where(:team_member_sites => {:site_code => site_codes } ) }

TeamMember.select("team_members.email, team_members.first_name, team_members.last_name").active.with_site_code(params[:site_code]).with_role(["senior_editing", "senior_and_reg_editing"]) 

Comme indiqué, la requête sélectionne toutes les colonnes.

Lorsque les 2 scopes utilisent des 'joins' au lieu de 'includes', la requête fonctionne : seules les 3 colonnes spécifiées sont sélectionnées.

0voto

Moin Haidar Points 521
Item.where("fulfilled = ?", true)
    .includes({:orders =>[:suppliers, :agents]}, :manufacturers)
    .select("users.name, users.created_at, orders.created_at, suppliers.name, agents.name").
    .order('orders.created_at DESC')

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