我使用的AR includes
方法來執行左外對象用戶和大廈,其中用戶可以或可以不具有一個建築協會之間JOIN:用ActiveRecord意外行爲包括
users = User.includes(:building).references(:buildings)
由於我使用的是references
,因此任何關聯的Building對象都將被加載。
我的期望是,我可以遍歷用戶列表,並檢查用戶是否擁有與其關聯的建築物而不觸發其他查詢,但是我發現實際上每當我嘗試訪問建築物時沒有一個用戶的屬性,AR使另一個SQL調用嘗試並檢索該建築物(儘管在隨後的嘗試中它只會返回零)。
這些查詢顯然是多餘的,因爲關聯在初始連接期間會被加載,並且似乎打敗了使用包含/引用進行加載的全部目的,因爲現在我正在查看N次查詢數到空關聯的數量。
users.each do | user |
# This will trigger a new query when building is not present:
# SELECT "buildings".* FROM "buildings" WHERE "buildings"."address" = $1 LIMIT 1 [["address", "123 my street"]]
if user.building
puts 'User has building'
else
puts 'User has no building'
end
end
用戶等級:
class User < ActiveRecord::Base
belongs_to :building, foreign_key: 'residence_id'
end
有沒有一種方法來檢查用戶的建築協會的存在,而不會觸發額外的查詢?
ON RAILS 4.2.0/POSTGRES
UPDATE:
謝謝@BoraMa爲組建該test。看起來我們正在跨越最近的Rails版本不同的行爲:
OUTPUT(鋼軌4.2.0):
User 1 has building
User 2 has building
User 3 has no building
D, [2016-05-26T11:48:38.147316 #11910] DEBUG -- : Building Load (0.2ms) SELECT "buildings".* FROM "buildings" WHERE "buildings"."id" = $1 LIMIT 1 [["id", 123]]
User 4 has no building
OUTPUT(鋼軌4.2.6)
User 1 has building
User 2 has building
User 3 has no building
User 4 has no building
OUTPUT(鋼軌5.0 .0)
User 1 has building
User 2 has building
User 3 has no building
User 4 has no building
採取跳投:
- 這個問題僅限於「晃來晃去外鍵(即residence_id 列不是零,但沒有相應的建築物對象)」 (感謝@FrederickCheung)
- 的問題已經解決像Rails 4.2的。 6
我期望類似於「ActiveRecord :: AssociationNotFoundError:在用戶上找不到名爲'Buildings'的關聯」錯誤。你能否確認查詢語法以及用戶 - >建立關聯定義? – messanjah
@messanjah就我個人而言,如果關聯不存在,那麼'user.building'將返回nil,這就是後續調用中發生的情況,但在第一次調用時總會觸發SQL查詢。 – Yarin
奇怪的是,我沒有觀察到這種行爲 - 我的無關聯只是返回零,沒有進一步的查詢。您在問題中給出的代碼確實是問題的最小工作示例? – BoraMa