web-dev-qa-db-fra.com

LEFT OUTER se joint à Rails 3

J'ai le code suivant:

@posts = Post.joins(:user).joins(:blog).select

qui est destiné à trouver tous les messages et à les renvoyer ainsi qu'aux utilisateurs et blogs associés. Cependant, les utilisateurs sont facultatifs, ce qui signifie que le INNER JOIN cette :joins génère ne renvoie pas beaucoup d'enregistrements.

Comment puis-je l'utiliser pour générer un LEFT OUTER JOIN au lieu?

85
Neil Middleton
@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").
              joins(:blog).select
111
Neil Middleton

Vous pouvez le faire avec includescomme indiqué dans le guide Rails :

Post.includes(:comments).where(comments: {visible: true})

Résulte en:

SELECT "posts"."id" AS t0_r0, ...
       "comments"."updated_at" AS t1_r5
FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id"
WHERE (comments.visible = 1)
75
WuTangTan

Je suis un grand fan de la gemme squeel :

Post.joins{user.outer}.joins{blog}

Il prend en charge les jointures inner et outer, ainsi que la possibilité de spécifier une classe/type pour les relations d'appartenance polymorphe.

11
plainjimbo

Utilisation eager_load:

@posts = Post.eager_load(:user)
10
Ricardo

Par défaut, lorsque vous passez ActiveRecord::Base#joins une association nommée, elle effectuera une INNER JOIN. Vous devrez passer une chaîne représentant votre jointure extérieure gauche.

De la documentation :

:joins - Soit un fragment SQL pour des jointures supplémentaires comme "LEFT JOIN comments ON comments.post_id = id "(rarement nécessaire), associations nommées sous la même forme utilisée pour le :include option, qui effectuera une INNER JOIN sur les tables associées, ou un tableau contenant un mélange de chaînes et d'associations nommées.

Si la valeur est une chaîne, les enregistrements seront renvoyés en lecture seule, car ils auront des attributs qui ne correspondent pas aux colonnes de la table. Passer :readonly => false pour remplacer.

8
DBA

Il existe une méthode left_outer_joins dans activerecord. Vous pouvez l'utiliser comme ceci:

@posts = Post.left_outer_joins(:user).joins(:blog).select
7
Ahmad Hussain

Bonne nouvelle, Rails 5 prend désormais en charge LEFT OUTER JOIN. Votre requête ressemblerait maintenant à:

@posts = Post.left_outer_joins(:user, :blog)
4
Dex
class User < ActiveRecord::Base
     has_many :friends, :foreign_key=>"u_from",:class_name=>"Friend"
end

class Friend < ActiveRecord::Base
     belongs_to :user
end


friends = user.friends.where(:u_req_status=>2).joins("LEFT OUTER JOIN users ON users.u_id = friends.u_to").select("friend_id,u_from,u_to,u_first_name,u_last_name,u_email,u_fbid,u_twtid,u_picture_url,u_quote")
0
Jigar Bhatt