2015-03-02 67 views
2

我使用Rails 4.2.0和ActiveRecord。我有Case型號,其中has_many :notes在rails中關聯關聯範圍的子查詢

我的主要目標是在一個查詢中獲取每個案例的最新備註。註釋字段應該是排序(ORDER BY notes.created_at,例如),我可以通過這樣的SQL查詢實現這一目標:

SELECT cases.*, notes.* FROM cases 
LEFT OUTER JOIN notes ON cases.id = notes.case_id AND notes.id = (
    SELECT id FROM notes 
    WHERE notes.case_id = cases.id 
    ORDER BY notes.created_at DESC 
    LIMIT 1 
) 
ORDER BY notes.created_at DESC 

我現在case.rb代碼如下:

has_one :latest_note, -> do 
    where('id' => Note.where('"case_id" = "cases"."id"').order(created_at: :desc).limit(1)) 
end, inverse_of: :case, class_name: 'Note' 

它工作正常,當eager_load使用: Case.eager_load(:latest_note).order('notes.created_at DESC')

SELECT "cases"."id" AS t0_r0, "cases"."created_at" AS t0_r1, "cases"."updated_at" AS t0_r2, "notes"."id" AS t1_r0, "notes"."case_id" AS t1_r1, "notes"."created_at" AS t1_r2, "notes"."updated_at" AS t1_r3 
FROM "cases" LEFT OUTER JOIN "notes" 
    ON "notes"."case_id" = "cases"."id" 
    AND "notes"."id" IN (
    SELECT "notes"."id" FROM "notes" 
    WHERE ("case_id" = "cases"."id") 
    ORDER BY "notes"."created_at" DESC 
    LIMIT 1 
) ORDER BY notes.created_at DESC 

但引發錯誤SQLite3::SQLException: no such column: cases.id沒有eager_loadCase.first.latest_note

SELECT "notes".* FROM "notes" 
WHERE "notes"."case_id" = ? AND "notes"."id" IN (
    SELECT "notes"."id" FROM "notes" 
    WHERE ("case_id" = "cases"."id") 
    ORDER BY "notes"."created_at" DESC 
    LIMIT 1 
) LIMIT 1 

附:有沒有關聯範圍的解決方案?通過joins的原始左連接不能與eager_load一起使用。如果沒有eager_load,它不會將數據庫中的值映射到對象 - 日期保持爲字符串,而不是DateTime對象。

回答

2

我剛剛找到了解決方法:

documentation我發現,其範圍可以接受的所有者對象作爲參數:

class User < ActiveRecord::Base 
    has_many :birthday_events, ->(user) { where starts_on: user.birthday }, class_name: 'Event' 
end 

所以,我的關係變成了:

has_one :latest_note, ->(kase) do 
    subquery = Note.order(created_at: :desc).limit(1) 
    subquery = kase.is_a?(Case) ? subquery.where(case_id: kase.id) : subquery.where('"case_id" = "cases"."id"') 
    where('id' => subquery) 
end, inverse_of: :case, class_name: 'Note' 

然而,Rails 4.2.0輸出:

DEPRECATION警告:關聯範圍'latest_note'是實例相關的(範圍塊帶有參數)。預加載在個體實例創建之前發生。這意味着沒有實例被傳遞給關聯作用域。這很可能會導致錯誤或不正確的行爲。加入,預加載和急切加載這些關聯將被棄用,並且將來會被刪除。 > {加入( - birthday_events,:`的has_many:

而且,這種解決方法不preload(單獨的SQL查詢)通過使用連接,而不是一個實例相關的where子句工作

+0

避免該警告「JOIN events on events.starts_on = users.birthday」},class_name:'Event'' – s2t2 2017-01-14 17:38:25