簡體   English   中英

渴望加載關聯 model 的最后一條記錄

[英]Eager loading the last record of an associated model

我有一張 model Invoice ,其中has_many Payments和一張 model Payment ,即belongs_to Invoice

發票.rb

class Invoice < ApplicationRecord
  has_many :payments, inverse_of: :invoice
end

付款.rb

class Payment < ApplicationRecord
  belongs_to :invoice
end

我們每月分批導出Invoice數據,我們需要每張Invoice的最后一次Payment。

在我們看來,我們目前正在為我們要導出的每個 Invoice 執行一次Invoice.payments.last ,並且我被要求阻止 N+1 查詢。

我嘗試將以下關聯添加到Invoice model:

has_one     :last_approved_payment,
              -> { invoice.payments.approved.last },
              class_name: "Payment", inverse_of: :invoice

但我收到以下錯誤:

Invoice.first.last_approved_payment
  Invoice Load (0.4ms)  SELECT "invoices"."id", "invoices"."user_id", "invoices"."invoiceable_type", "invoices"."invoiceable_id", "invoices"."status", "invoices"."number", "invoices"."period", "invoices"."external_id", "invoices"."external_status", "invoices"."created_at", "invoices"."updated_at", "invoices"."due_date", "invoices"."metadata", "invoices"."rejection_code", "invoices"."retry_attempt", "invoices"."next_retry_date", "invoices"."last_retry_date", "invoices"."expire_date", "invoices"."external_service", "invoices"."external_type", "invoices"."external_info", "invoices"."account_id", "invoices"."temp_due_date", "invoices"."next_attempt_date", "invoices"."last_attempt_date", "invoices"."processing_stage", "invoices"."amount_cents", "invoices"."amount_currency", "invoices"."desist_retrying" FROM "invoices" ORDER BY "invoices"."id" ASC LIMIT $1  [["LIMIT", 1]]
  Payment Load (0.3ms)  SELECT "payments"."id", "payments"."operation_id", "payments"."status", "payments"."status_detail", "payments"."payment_type", "payments"."external_reference", "payments"."payer_email", "payments"."date_created", "payments"."date_approved", "payments"."money_release_date", "payments"."comment", "payments"."created_at", "payments"."updated_at", "payments"."user_id", "payments"."operation_type", "payments"."reason", "payments"."reasonable_type", "payments"."reasonable_id", "payments"."invoice_id", "payments"."metadata", "payments"."account_id", "payments"."amount_cents", "payments"."amount_currency", "payments"."payer_id_ciphertext" FROM "payments" LIMIT $1  [["LIMIT", 11]]
  Payment Load (0.4ms)  SELECT "payments"."id", "payments"."operation_id", "payments"."status", "payments"."status_detail", "payments"."payment_type", "payments"."external_reference", "payments"."payer_email", "payments"."date_created", "payments"."date_approved", "payments"."money_release_date", "payments"."comment", "payments"."created_at", "payments"."updated_at", "payments"."user_id", "payments"."operation_type", "payments"."reason", "payments"."reasonable_type", "payments"."reasonable_id", "payments"."invoice_id", "payments"."metadata", "payments"."account_id", "payments"."amount_cents", "payments"."amount_currency", "payments"."payer_id_ciphertext" FROM "payments" LIMIT $1  [["LIMIT", 11]]
**NameError: undefined local variable or method `invoice' for #<Payment::ActiveRecord_Relation:0x000055b544ccf138>
from /home/vm/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.6/lib/active_record/relation/delegation.rb:109:in `method_missing'**

您不需要在 model 關系中顯式添加默認 scope,您可以做的只是在檢索發票時預加載payments表;

Invoice.includes(:payments)

盡管如果您只是 select 兩種模型真正需要的東西,IMO 會更好,但您可以使用select通過子查詢來實現:

Invoice.select(
  :id,
  "(SELECT p.id,
    FROM payments p
    WHERE p.invoice_id = invoices.id
    ORDER BY created_at DESC
    LIMIT 1) AS payment_id"
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM