簡而言之,我遇到了一個可怕的2(n)查詢問題。 如果n =數據庫中的技能數量,那麼我的角色#編輯表單將花費2(n)個查詢來加載頁面。它會在每個技能中選擇一次PlayerSkill(連接表),並且每個技能都會查找一次技能。可能與nested_attributes緊密加載關聯嗎?
下面是一些我認爲與情況相關的代碼。實質上,這個過程中涉及的模型,視圖和控制器,不是模型驗證,而是我不關心的操作。
控制器:
# GET /characters/1/edit
def edit
@character = Character.find(params[:id], :include => {:player_skills => :skill})
stub_player_skills
end
private
def stub_player_skills
@skills = Skill.find(:all)
@skills.each do |skill|
if (skill.player_skills.empty?)
ps = @character.player_skills.build(:skill_id => skill.id, :name => skill.name)
end
end
end
模型(S):
class Character < ActiveRecord::Base
belongs_to :user
belongs_to :campaign
has_many :sheets, :dependent => :destroy
has_many :tokens, :dependent => :destroy
has_many :player_skills, :dependent => :destroy
has_many :skills, :through => :player_skills
accepts_nested_attributes_for :player_skills, :allow_destroy => true
end
違規的視圖(HAML):
%h1
Editing Character
- form_for @character do |f|
= f.error_messages
%p
= f.label :name
%br
= f.text_field :name
%p
= f.label :race
%br
= f.text_field :race
%p
= f.label :char_class
%br
= f.text_field :char_class
%p
-f.fields_for :player_skills do |ps|
=ps.object.skill.name
=ps.text_field :level
=ps.hidden_field :skill_id
-unless ps.object.new_record?
=ps.check_box '_destroy'
=ps.label '_destroy', 'Remove'
%br
%p
= f.submit
我瞭解的情況是,預先加載存在以抓取關聯(大致)一個額外的查詢。
我需要正確地應用在兩個領域的急切加載,我只是在如何做到這一點上的損失。
在stub_player_skills方法中,它需要創建一個PlayerSkill對象,假定該字符還沒有。 它可以受益於這裏的熱切加載,因爲它循環了數據庫中的每項技能。這是第一個「n查詢」來自哪裏。
然後在視圖上,fields_for循環遍歷所有我們累積起來的PlayerSkills,因爲當我調用= ps.object.skill.name打印出技能名稱時,無法在這裏急切加載,做了一次技能查詢,它引入了第二組「n查詢」。
我主要關注的是視圖層,我找不到任何文檔(Rails API或其他),說明如何使用fields_for生成嵌套表單,以便如何加載關聯。
感謝您的任何和所有響應:) 〜羅比
這並不完美,因爲我仍然需要遍歷所有可能的技能(請參閱stub_player_skills)並檢查PlayerSkill是否已經存在。 想象一下,我們有技能#1,#2和#3。如果我有技能#1和#3,那麼我們需要將#2排除。 我認爲問題是我使用ActiveRecord來做另一個「查找」,我應該只是在我的業務邏輯中迭代數組? – Robbie 2010-09-27 23:42:47
對不起,我完全錯過了那部分。我可以看到你現在想做的事情......我會修改我的帖子。 – Coderama 2010-09-27 23:50:27
稍微修改我已經得到了這個工作,並且控制器不再需要n個查詢來加載PlayerSkills。然而,該視圖仍然需要n個查詢,因爲我讓它調用ps.object.skill.name;在我看來,這可能是Rails如何處理fields_for的一個限制,這很不幸。 – Robbie 2010-09-28 00:12:02