LEFT OUTER joins in Rails 3

Ruby on-RailsRubyActiverecord

Ruby on-Rails Problem Overview


I have the following code:

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

which is meant to find all posts and return them and the associated users and blogs. However, users are optional which means that the INNER JOIN that :joins generates is not returning lots of records.

How do I use this to generate a LEFT OUTER JOIN instead?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

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

Solution 2 - Ruby on-Rails

You can do with this with includes as documented in the Rails guide:

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

Results in:

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)

Solution 3 - Ruby on-Rails

I'm a big fan of the squeel gem:

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

It supports both inner and outer joins, as well as the ability to specify a class/type for polymorphic belongs_to relationships.

Solution 4 - Ruby on-Rails

Use eager_load:

@posts = Post.eager_load(:user)

Solution 5 - Ruby on-Rails

By default when you pass ActiveRecord::Base#joins a named association, it will perform an INNER JOIN. You'll have to pass a string representing your LEFT OUTER JOIN.

From the documentation:

> :joins - Either an SQL fragment for additional joins like "LEFT JOIN > comments ON comments.post_id = id" (rarely needed), named associations > in the same form used for the :include option, which will perform an > INNER JOIN on the associated table(s), or an array containing a > mixture of both strings and named associations. > > If the value is a > string, then the records will be returned read-only since they will > have attributes that do not correspond to the table‘s columns. Pass > :readonly => false to override.

Solution 6 - Ruby on-Rails

There is a left_outer_joins method in activerecord. You can use it like this:

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

Solution 7 - Ruby on-Rails

Good news, Rails 5 now supports LEFT OUTER JOIN. Your query would now look like:

@posts = Post.left_outer_joins(:user, :blog)

Solution 8 - Ruby on-Rails

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")

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNeil MiddletonView Question on Stackoverflow
Solution 1 - Ruby on-RailsNeil MiddletonView Answer on Stackoverflow
Solution 2 - Ruby on-RailsWuTangTanView Answer on Stackoverflow
Solution 3 - Ruby on-RailsplainjimboView Answer on Stackoverflow
Solution 4 - Ruby on-RailsRicardoView Answer on Stackoverflow
Solution 5 - Ruby on-RailsDBAView Answer on Stackoverflow
Solution 6 - Ruby on-RailsAhmad HussainView Answer on Stackoverflow
Solution 7 - Ruby on-RailsDexView Answer on Stackoverflow
Solution 8 - Ruby on-RailsJigar BhattView Answer on Stackoverflow