Rails 5.を使用しています。次のモデルを持っています...
class Order < ApplicationRecord
...
has_many :line_items, :dependent => :destroy
LineItemモデルには「discount_applied」という属性があります。 「discount_applied」フィールドがnilでないラインアイテムのインスタンスがゼロであるすべての注文を返したいのですが。このようなFinderメソッドを作成するにはどうすればよいですか?
効率的ではありませんが、あなたの問題を解決できると思いました:
orders = Order.includes(:line_items).select do |order|
order.line_items.all? { |line_item| line_item.discount_applied.nil? }
end
更新:
すべてのラインアイテムに割引がない注文を見つける代わりに、割引が適用されたラインアイテムを持つすべての注文を出力結果から除外できます。これは、where句内でsubqueryを使用して実行できます。
# Find all ids of orders which have line items with a discount applied:
excluded_ids = LineItem.select(:order_id)
.where.not(discount_applied: nil)
.distinct.map(&:order_id)
# exclude those ids from all orders:
Order.where.not(id: excluded_ids)
これらを1つのFinderメソッドで組み合わせることができます。
Order.where.not(id: LineItem
.select(:order_id)
.where.not(discount_applied: nil))
お役に立てれば
ここにあなたの問題の解決策があります
order_ids = Order.joins(:line_items).where.not(line_items: {discount_applied: nil}).pluck(:id)
orders = Order.where.not(id: order_ids)
最初のクエリはOrders
のIDを返し、少なくとも1つのline_item
がdiscount_applied
を持っています。 2番目のクエリは、line_item
を持つdiscount_applied
のインスタンスがゼロの場合にすべてのorders
を返します。
Discount_appliedがnilであるすべてのレコードが必要な場合:
Order.includes(:line_items).where.not(line_items: {discount_applied: nil})
(n + 1の問題を回避するためにincludeを使用)または
Order.joins(:line_items).where.not(line_items: {discount_applied: nil})
NOT EXISTS
SQLの機能。少なくともMySQLとPostgreSQLの両方で使用できます
このようになります
class Order
has_many :line_items
scope :without_discounts, -> {
where("NOT EXISTS (?)", line_items.where("discount_applied is not null")
}
end