Skip to content

Instantly share code, notes, and snippets.

@mrwillihog
Last active June 24, 2017 19:53
Show Gist options
  • Save mrwillihog/78c10038c4fd04bbab276b5dc2ad1d20 to your computer and use it in GitHub Desktop.
Save mrwillihog/78c10038c4fd04bbab276b5dc2ad1d20 to your computer and use it in GitHub Desktop.
Left joining in RoR

Left joins

Given 3 models: User, Book, Reading. How to return a list of all books and mark the ones read by a given user.

The result could look something like:

[
  {
    "id": 1,
    "title": "To Kill a Mockingbird",
    "read": false
  },
  {
    "id": 2,
    "title": "East of Eden",
    "read": true
  },
  {
    "id": 3,
    "title": "On the Road",
    "read": false
  }
]

Where read indicates there is a Reading object linking this Book to this User

class Book < ApplicationRecord
has_many :readings, dependent: :destroy
validates :title, presence: true
end
class BookSerializer < ActiveModel::Serializer
attributes :id, :title, :read
def read
object.read
end
end
SELECT books.*, CASE WHEN readings.id IS NULL THEN false ELSE true END as read
FROM "books"
LEFT OUTER JOIN "readings" ON "readings"."book_id" = "books"."id" and user_id = '<some id>';
class Reading < ApplicationRecord
belongs_to :user
belongs_to :book
end
class User < ApplicationRecord
has_many :readings, dependent: :destroy
validates :name, present: true
end
class UsersController < ApplicationController
def reading_list
books = Book
.select('books.*, CASE WHEN readings.id IS NULL THEN false ELSE true END as read')
.joins("LEFT OUTER JOIN readings ON reagins.book_id = books.id AND readings.user_id = '#{current_user.id}'")
.all
render json: books
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment