Today I Learned

hashrocket A Hashrocket project

ActiveRecord Query with `and`

ActiveRecord has an and method for querying.

Post.where(id: [1, 2]).and(Post.where(id: [2, 3]))
# SELECT "posts".* FROM "posts" WHERE "posts"."id" IN (1, 2) AND "posts"."id" IN (2, 3)

More likely you'd write that by chaining wheres:

Post.where(id: [1, 2]).where(id: [2, 3])

However, and really shines if you have more complicated querying with nesting of ANDs and ORs:

SELECT "posts".* 
FROM "posts" 
WHERE "posts"."id" IN (1, 2) 
  AND ("posts"."title" = 'title'
    OR "posts"."body" IS NOT NULL)

How would you write this in ActiveRecord? A first pass with where and or doesn't get us what we want:

Post.where(id: [1,2])
  .where(title: 'title')
  .or(Post.where.not(body: nil))

# SELECT "posts".* 
# FROM "posts" 
# WHERE ("posts"."id" IN (1, 2) 
#   AND "posts"."title" = 'title' 
#   OR "posts"."body" IS NOT NULL)

Instead of A AND (B OR C) we get A AND B OR C. We can use a well-placed and to get the right grouping of conditions:

Post.where(id: [1,2])
  .and(Post.where(title: 'title')
    .or(Post.where.not(body: nil)))

# SELECT "posts".*
# FROM "posts"
# WHERE "posts"."id" IN (1, 2)
#   AND ("posts"."title" = 'title'
#     OR "posts"."body" IS NOT NULL)

Docs

h/t Craig Hafer

See More #rails TILs
Looking for help? Hashrocket has been an industry leader in Ruby on Rails since 2008. Rails is a core skill for each developer at Hashrocket, and we'd love to take a look at your project. Contact us and find out how we can help you.