Just briefly, I have run into a dreaded 2(n) queries problem. If n = the number of skills in the database, then my characters#edit form will take 2(n) queries to load the page. It will SELECT a PlayerSkill (the join table) once every skill, and it will look up the Skill once per skill.
Here is some code which I believe is pertinent to the situation. In essence, the models, views, and controllers involved in this process, less the model validations and less the actions I'm not concerned about.
The controller:
# 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
The model(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
The offending view (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
My understanding of the situation is that eager loading exists to grab the association in (roughly) a single extra query.
I need to properly apply eager loading in two areas, and I am just at a loss regarding how to do it.
In the stub_player_skills method, it needs to create a PlayerSkill object assuming the character does not already have one. It could benefit from eager loading here because it loops through each skill in the database. This is where the first "n-queries" are coming from.
Then on the view, fields_for loops through all the PlayerSkills we've racked up, because there is no way to eager load here, when I call =ps.object.skill.name to print out the skill's name, it does a Skill lookup, which brings in the second set of "n-queries."
My primary concern lies in the view layer, I cannot find any documentation (Rails API or otherwise) that states how you could eager load the associations if you're using fields_for to generate a nested form.
Thanks for any and all responses :) ~Robbie