In my scenario, I have a BlogPost
model that has_and_belongs_to_many :categories
. I want to filter out Blog Posts that belong to specific Categories, while still allowing for uncategorized Blog Posts (hence the need for a LEFT OUTER JOIN).
I expected this to work:
BlogPost.active.includes(:categories).where.not(categories: { id: [1, 2, 3] })
But it doesn't filter correctly because it puts the conditions at the end of the query, outside the LEFT OUTER JOIN (see this SO question / answer for the reason: SQL join: where clause vs. on clause)
This works, but it is ugly:
BlogPost.active.joins("LEFT OUTER JOIN blog_posts_categories
ON blog_posts_categories.blog_post_id = blog_posts.id
AND blog_posts_categories.category_id NOT IN(1, 2, 3)")
Is there an ActiveRecord-friendly way to add conditionals to the ON clause of a LEFT OUTER JOIN without manually typing it out the way I did?