enjaku
enjaku

Reputation: 346

finding all the records where associated records have a specific attribute value only

Let's say I have two models Product and Payment with a has_many association.

class Product < ApplicationRecord
  has_many :payments
end
class Payment < ApplicationRecord
  belongs_to :product
end

Payment model has an attribute paid which can be true or false. How can i find all the products which have only payments with paid attribute set to false?

I tried:

Product.joins(:payments).where(payments: { paid: false }).distinct

but it returns the products where at least one payment is false when I need all of them to be false.

Upvotes: 0

Views: 769

Answers (2)

Tyrone Wilson
Tyrone Wilson

Reputation: 4638

I am a big fan of the Ransack gem which simplifies a lot of queries with ActiveRecord

You are looking for products where there are only payments of false so you can add two clauses in your ransack query to achieve your desired result.

First install ransack and then use this to see if you get your desired result

Product.ransack(
  payments_paid_eq: false, 
  payments_paid_not_eq: true)
.result
.distinct

This is a slightly confusing query in some ways but in essence you are saying return all products with payments false and don't return ones with payment true.

An alternative approach without using the ransack gem would be the following

Product.joins(:payments)
  .where(payments: {paid: false})
  .where.not(payments: {paid: true})
  .distinct

Upvotes: 1

jvillian
jvillian

Reputation: 20253

I think this might do what you're looking for:

Product.
  where(id: Payment.where(paid: false).pluck(:product_id)).
  where.not(id: Payment.where(paid: true).pluck(:product_id))

Upvotes: 0

Related Questions