Rails
SQL

Railsで生SQLを書かずにLEFT JOINする方法

More than 5 years have passed since last update.

弊社ブログ記事からの転載です
Railsで生SQLを書かずにLEFT JOINする方法 @ lab.heathrow

例えばこんな関連のモデルがあったとして

class Blog
  has_many :posts
  attr_accessible :enable
end

class User
  has_many :posts
  attr_accessible :enable
end

class Post
  belongs_to :blog
  belongs_to :user
end

Blog(enable=true)もしくはUser(enable=true)に属するPostを取得したいとき

MySQLで書くと、こんな感じ。

SELECT `posts`.*
FROM `posts`
LEFT JOIN `blogs` ON `blogs`.`id` = `posts`.`blog_id`
LEFT JOIN `users` ON `users`.`id` = `posts`.`user_id`
WHERE
  `blogs`.`enable` = 1
  OR
  `users`.`enable` = 1

このLEFT JOINの部分をActiveRecordでどう書くかというのが、今回のお話

あまり良くない書き方

ネットを検索すると、よくこんな感じのやり方をしているサンプルを見つけます
JOIN句を生SQLで書いてます

Post.joins("LEFT OUTER JOIN `users` ON `users`.`id` = `posts`.`user_id`")...

DBがMySQLの場合、これは正しく動作します。
しかし、DBが例えばSQLServerの場合、これはシンタックスエラーとなってしまいます。

せっかくActiveRecordが裏側のDBを抽象化してくれているのにもったいない
見栄えもわるいし、書くのも長ったらしくてめんどくさいですね

正しい方法

includesを使うことによって、このように書くことができます

Post.includes(:blog, :user).where(Blog.arel_table[:enable].eq(true).or(User.arel_table[:enable].eq(true))

これでActiveRecordがよろしくやってくれます。
DBがMySQLであろうとSQLServerであろうと関係なく、LEFT JOINされた正しいSQLを発行してくれます。


弊社ブログ記事からの転載です
Railsで生SQLを書かずにLEFT JOINする方法 @ lab.heathrow