Rails 5 is cool!
Rails 5 introduced the left connections ( LEFT JOIN , it explains what kind of animal it is ), so this is done without any digging under the hood, rail means:
- take posts
- left-connect with their permanent categories
- select posts that instead of the post-category turned out to be
NULL s- it is enough to check that the
post_id value is NULL , since it is an association key, it falls into the predicate of the connection, and NULL not equal to NULL , therefore only the lines for which no post-category was found under the condition
Post.left_joins(:posts_and_categories) .merge(PostsAndCatrgory.where(post_id: nil))
But in older versions ...
And earlier I would suggest (and suggested ) using the NOT EXISTS SQL:
Post.where( "NOT EXISTS (?)", PostsAndCategory.where("posts_and_categories.post_id = post.id") )
... but you can get rid of the pieces of SQL by taking Arel (the ActiveRecord query designer is already built on it, so you don’t need to install anything else):
Post.where( PostsAndCategory.where( post_id: Post.arel_table[:id] ) .exists .not )
The second solution looks even more transparent, it says more directly what is being searched for. Is that the speed of work is worth checking. But it does not use data on associations, which is a minus.