web-dev-qa-db-ja.com

Rails Finderメソッドをどのように記述すれば、has_manyのどの項目にも非nilフィールドがありませんか?

Rails 5.を使用しています。次のモデルを持っています...

class Order < ApplicationRecord
    ...
    has_many :line_items, :dependent => :destroy

LineItemモデルには「discount_applied」という属性があります。 「discount_applied」フィールドがnilでないラインアイテムのインスタンスがゼロであるすべての注文を返したいのですが。このようなFinderメソッドを作成するにはどうすればよいですか?

8
Dave

効率的ではありませんが、あなたの問題を解決できると思いました:

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))

お役に立てれば

0
Mosaaleb

ここにあなたの問題の解決策があります

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_itemdiscount_appliedを持っています。 2番目のクエリは、line_itemを持つdiscount_appliedのインスタンスがゼロの場合にすべてのordersを返します。

0
Naveed

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})
0
bhavna garg

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
0
Mathieu J.