[英]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.