web-dev-qa-db-fra.com

Rails 3 - sélectionnez avec Include?

Voici une sélection imbriquée avec include:

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

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

Comment puis-je obtenir la requête pour ne sélectionner que des champs spécifiques?

  • user.name, user.created_at
  • order.created_at
  • nom du fournisseur
  • nom d'agent
  • nom du Fabricant
37
sscirrus

Il existe une méthode de sélection dans ARel, mais vous devez utiliser les noms de table corrects (au pluriel et méfiez-vous 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 non incluses" - @Bhavesh_A_P

Remarque:

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

32
Patrick Klingemann

En fait, nous ne pouvons pas utiliser select with includes. Il ne peut être utilisé qu'avec des jointures.

17
Bhaveshkumar

Le problème n'est pas résolu en incluant un appel à la méthode 'select' dans la chaîne. Dans une ActiveRecord :: Relation similaire que nous avons construite, l'appel de "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 portées utilisent 'jointes' au lieu de 'inclut', la requête fonctionne: seules les 3 colonnes spécifiées sont sélectionnées.

5
Byofuel
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')
0
Moin Haidar