Reputation: 346
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
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
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