弊社ブログ記事からの転載です
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