Frage

Nur kurz, ich habe in einen gefürchteten 2 (n) lief abfragt Problem. Wenn n = die Anzahl der Fähigkeiten in der Datenbank, dann wird meine Zeichen # bearbeiten Form 2 (n) Abfragen, um die Seite zu laden. Es wird eine PlayerSkill SELECT (die Join-Tabelle) einmal jedes Können, und es wird die Fähigkeit einmal pro Fertigkeit nachschlagen.

Hier ist ein Code, den ich glaube, um die Situation relevant sind. Im Wesentlichen sind die Modelle, Ansichten und Controller an diesem Prozess beteiligt, weniger die Modellvalidierungen und weniger die Handlungen ich etwa nicht betroffen.

Der 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

Das Modell (e):

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

Die fehlbare Ansicht (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

Mein Verständnis für die Situation ist, dass eifrig Laden existiert der Verein in (ungefähr) eine einzige zusätzliche Abfrage zu greifen.

Ich brauche eifrig Laden in zwei Bereichen richtig anzuwenden, und ich bin nur mit einem Verlust in Bezug auf, wie es geht.

In der stub_player_skills Methode, braucht es eine PlayerSkill Objekt erstellen das Zeichen unter der Annahme nicht bereits eine haben. Es könnte hier von eifrigen Läden profitieren, weil sie durch jede Fertigkeit in der Datenbank-Schleifen. Dies ist, wo die ersten „n-Abfragen“ kommen aus.

Dann auf der Ansicht, fields_for Schleifen durch alle player wir zerbrochen haben, denn es gibt keine Möglichkeit zu eifrig Last hier, wenn ich rufe = ps.object.skill.name die Fähigkeit des Namens auszudrucken, es tut eine Fähigkeit Lookup, die in dem zweiten Satz bringt "N-Abfragen."

Mein Hauptanliegen liegt in der View-Ebene, finde ich keine Dokumentation (Rails API oder auf andere Weise), dass die Staaten, wie Sie eifrig Last könnten die Assoziationen, wenn Sie fields_for verwenden eine verschachtelte Form zu erzeugen.

Vielen Dank für jeden und alle Antworten :) ~ Robbie

War es hilfreich?

Lösung

Können Sie dies versuchen und sehen, ob es funktionieren wird?

Sie können Ihr Modell den Weg halten es ist.

Ihr Controller kann dann so aussehen:

def edit
  # Get all the skill objects once only
  skills = Skill.find(:all)

  # Used to extract Skill#name
  skills_hash = {}
  skills.map { |s| skills_hash[s.id] = s.name }

  # Create an array of the skill-ids
  skill_ids = skills.map { |s| s.id }

  @character = Character.find(params[:id])

  # Determine the character's missing skills
  skill_ids -= @character.player_skill_ids

  # Build all of the missing skills
  skill_ids.each do |id|
    @character.player_skills.build(:skill_id => id, :name => skills_hash[id])
  end
end

Andere Tipps

Bei anyones interessierte in meiner "endgültigen" Lösung für dieses Problem:

Ich habe zu speichern ein Array der Geschicklichkeit Namen zurückgegriffen, und Referenzierung in der Ansicht über einen Zähler, wie hier zu sehen:

  %p
    - index = 0
    -f.fields_for :player_skills do |ps|
      =@skill_arr[index]
      =ps.text_field :level
      =ps.hidden_field :skill_id
      -unless ps.object.new_record?
        =ps.check_box '_destroy'
        =ps.label '_destroy', 'Remove'
      - index += 1
      %br

In der Steuerung, ich habe fast die ganze Logik auf die stub_player_skills Methode bewegt, wo es hingehört, und eine Seite aus Coderama Buch nehmen, ich habe kommen mit diesem:

  private
    def stub_player_skills
      @skills = Skill.find(:all)
      @skills.each do |skill|
        skill_exists = @character.player_skills.select do |i|
          i.skill_id == skill.id
        end
        if skill_exists.empty?
          ps = @character.player_skills.build(:skill_id => skill.id, :name => skill.name)
        end
      end

      @skill_arr = @character.player_skills.map do |el|
        el.name.nil? ? el.skill.name : el.name
      end
    end

In der Modellschicht, musste ich einfach :include => :skill auf dem has_many. Durch Beziehung loswerden ein paar Anfragen bekommen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top