2010-03-12 16 views
5

Ich habe ein dreistufiges verschachteltes Formular in Rails. Das Setup ist so: Projekte haben viele Meilensteine ​​und Meilensteine ​​haben viele Hinweise. Das Ziel ist es, alles innerhalb der Seite mit JavaScript zu bearbeiten, wo wir einem Projekt auf der Seite mehrere neue Meilensteine ​​hinzufügen und neue Notizen zu neuen und bestehenden Meilensteinen hinzufügen können.Mehrere verschachtelte verschachtelte Formulare als "schmutzig" in Rails markieren

Alles funktioniert wie erwartet, mit der Ausnahme, dass, wenn ich zu einem bestehenden Meilenstein (neue Meilensteine ​​funktionieren, wenn die Noten zu ihnen hinzufügen) neuen Notizen hinzufügen, werden nicht speichern die neuen Noten, wenn ich eines der Felder bearbeiten, die eigentlich gehören zum Meilenstein um das Formular "dreckig"/bearbeitet zu markieren.

Gibt es eine Möglichkeit, den Meilenstein so zu kennzeichnen, dass die neuen Notizen, die hinzugefügt wurden, gespeichert werden?

Edit: sorry, es ist schwer, in den gesamten Code einzufügen, weil es so viele Teile ist, aber hier geht:

Modelle

class Project < ActiveRecord::Base 
    has_many :notes, :dependent => :destroy 
    has_many :milestones, :dependent => :destroy 

    accepts_nested_attributes_for :milestones, :allow_destroy => true 
    accepts_nested_attributes_for :notes, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } 
end 

class Milestone < ActiveRecord::Base 
    belongs_to :project 
    has_many :notes, :dependent => :destroy 

    accepts_nested_attributes_for :notes, :allow_destroy => true, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } 
end 

class Note < ActiveRecord::Base 
    belongs_to :milestone 
    belongs_to :project 

    scope :newest, lambda { |*args| order('created_at DESC').limit(*args.first || 3) } 
end 

Ich bin ein jQuery-basierte verwenden, unaufdringliche Version von Ryan Bates Combo Helfer/JS-Code, um dies zu tun.

Anwendung Helper

def add_fields_for_association(f, association, partial) 
    new_object = f.object.class.reflect_on_association(association).klass.new 
    fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| 
    render(partial, :f => builder) 
    end 
end 

ich mache das Formular für den Verein in einem versteckten div und dann den folgenden JavaScript verwenden, um es zu finden und es nach Bedarf hinzufügen.

JavaScript

function addFields(link, association, content, func) { 
    var newID = new Date().getTime(); 
    var regexp = new RegExp("new_" + association, "g"); 
    var form = content.replace(regexp, newID); 
    var link = $(link).parent().next().before(form).prev(); 
    if (func) { 
     func.call(); 
    } 
    return link; 
} 

Ich bin das einzig andere relevante Stück Code zu erraten, dass ich denken kann, würde die Methode in dem NotesController erstellen sein:

def create 
    respond_with(@note = @owner.notes.create(params[:note])) do |format| 
    format.js { render :json => @owner.notes.newest(3).all.to_json } 
    format.html { redirect_to((@milestone ? [@project, @milestone, @note] : [@project, @note]), :notice => 'Note was successfully created.') } 
    end 
end 

Die @owner Ivar wird im Folgenden vor dem Filter erstellt:

def load_milestone 
    @milestone = @project.milestones.find(params[:milestone_id]) if params[:milestone_id] 
end 

def determine_owner 
    @owner = load_milestone || @project 
end 

Die Sache ist, alles scheint gut zu funktionieren, außer wenn ich neue Notizen zu bestehenden Meilensteinen hinzufüge. Der Meilenstein muss "berührt" werden, damit neue Notizen gespeichert werden können, sonst wird Rails nicht aufpassen.

+0

Meilensteine ​​'accept_nested_attributes_for: notes'? auch ein Code könnte hilfreich sein. – Anurag

+0

Code oben hinzugefügt! :) – simplesessions

Antwort

2

Dies ist bug #4242 in Rails 2.3.5 und es hat fixed gewesen in Schienen 2.3.8.

+0

Vielen Dank! Nach Monaten der Qual hast du mir die Antwort gegeben. Ich dachte, ich wäre verrückt, weil niemand zu wissen schien, wovon ich rede. – simplesessions

0

Ich denke, dass Ihre Modelle falsch sind. Die Notizen haben keine direkte Beziehung zum Projekt. Sie sind durch Meilensteine.

versuchen diese

class Project < ActiveRecord::Base 
    has_many :milestones, :dependent => :destroy 
    has_many :notes, :through => :milestones 
    accepts_nested_attr ibutes_for :milestones, :allow_destroy => true 
end 

class Milestone < ActiveRecord::Base 
    belongs_to :project 
    has_many :notes, :dependent => :destroy 

    accepts_nested_attributes_for :notes, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } 
end 

class Note < ActiveRecord::Base 
    belongs_to :milestone 
end 

Update: Hier ist der Code, der auf der Grundlage der neuen Informationen für mich gearbeitet:

## project controller 

# PUT /projects/1 
def update 
    @project = Project.find(params[:id]) 

    if @project.update_attributes(params[:project]) 
    redirect_to(@project) 
    else 
    render :action => "edit" 
    end 
end 

# GET /projects/1/edit 
def edit 
    @project = Project.find(params[:id]) 
    @project.milestones.build 
    for m in @project.milestones 
    m.notes.build 
    end 
    @project.notes.build 
end 

## edit.html.erb 
<% form_for(@project) do |f| %> 
    <%= f.error_messages %> 

    <p> 
    <%= f.label :name %><br /> 
    <%= f.text_field :name %> 
    </p> 
    <% f.fields_for :notes do |n| %> 
     <p> 
     <div> 
      <%= n.label :content, 'Project Notes:' %> 
      <%= n.text_area :content, :rows => 3 %> 
     </div> 
     </p> 
    <% end %> 
    <% f.fields_for :milestones do |m| %> 
     <p> 
     <div> 
      <%= m.label :name, 'Milestone:' %> 
      <%= m.text_field :name %> 
     </div> 
     </p> 
     <% m.fields_for :notes do |n| %> 
      <p> 
      <div> 
       <%= n.label :content, 'Milestone Notes:' %> 
       <%= n.text_area :content, :rows => 3 %> 
      </div> 
      </p> 
     <% end %> 
    <% end %> 
    <p> 
    <%= f.submit 'Update' %> 
    </p> 
<% end %> 
+0

Nein, sie haben Recht. Projekte können auch eigene Notizen haben.Danke für den Hinweis! Alles funktioniert wie geplant. Ich wollte nur wissen, wie ich Rails beim Speichern mitteilen kann, dass Projekt-Meilenstein-Notizen (als Teil von * existierenden * Meilensteinen) gespeichert werden sollen, obwohl die Projekt-Meilensteine ​​selbst nicht berührt wurden. Es scheint die Notizen der Projekt-Meilensteine ​​zu ignorieren, obwohl sie neu sind, es sei denn, ich bearbeite ein Feld im Meilenstein. – simplesessions

+0

Entschuldigung, dass ich ursprünglich nicht festgestellt habe, dass Notizen auch zu Projekten gehören können. – simplesessions

+0

Danke für das Update! Es funktioniert immer noch nicht für mich. Das Javascript, das ich oben habe, fügt einem Formular dynamisch neue Notizen hinzu und gibt ihnen IDs basierend auf der aktuellen Zeit. Regelmäßige Formulare wie das in Ihrem Update funktionieren großartig, neu erstellte Notizen funktionieren jedoch nur, wenn ich den Meilenstein bearbeite. – simplesessions

Verwandte Themen