Posted at

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