2013-02-14 2 views
22

Ich verwende build, fields_for und accepts_nested_attributes_for, um einen neuen Registrierungshinweis auf dem gleichen Formular wie eine neue Registrierung (hat viele Registrierungshinweise) zu erstellen. Groß.Wie bekomme ich Rails build und fields_for um nur einen neuen Datensatz zu erstellen und nicht existierende zu enthalten?

Problem: Im Bearbeitungsformular für die bestehende Registrierung möchte ich eine neue Registrierungsnotiz erstellen, aber ich möchte kein Feld für jede vorhandene Registrierungsnotiz sehen.

Ich habe diesen

class Registration < ActiveRecord::Base 
    attr_accessible :foo, :bar, :registration_notes_attributes 
    has_many :registration_notes 
    accepts_nested_attributes_for :registration_notes 
end 

und dies

class RegistrationsController < ApplicationController 
    def edit 
    @registration = Registration.find(params[:id]) 
    @registration.registration_notes.build 
    end 
end 

und in der Ansicht Ich tue dies:

<%= form_for @registration do |r| %> 
    <%= r.text_field :foo %> 
    <%= r.text_field :bar %> 
    <%= r.fields_for :registration_notes do |n| %> 
    <%= n.text_area :content %> 
    <% end %> 
<% end %> 

und es wird einen leeren Textbereich für ein neuen zu schaffen Registrierungsschein (gut) und jeder bestehende Registrierungsvermerk für th bei der Registrierung (nein danke).

Gibt es eine Möglichkeit, nur eine neue Notiz für diese Registrierung zu erstellen und die vorhandenen in Ruhe zu lassen?

Antwort

62

EDIT: Meine bisherige Antwort (siehe unten) mich nervt, weil es nicht sehr schön ist (es Schleifen noch durch alle anderen registration_notes unnötig). Nach dem Lesen der beste Weg, um das Verhalten der OP wollte zu bekommen, ist die API ein bisschen mehr, zu ersetzen:

<%= r.fields_for :registration_notes do |n| %> 

mit:

<%= r.fields_for :registration_notes, @registration.registration_notes.build do |n| %> 

fields_for nimmt optional einen zweiten Parameter, der die spezifische Aufgabe ist es, übergeben Sie an den Erbauer (see the API), der inline gebaut wird. Es ist wahrscheinlich besser, die neue Notiz im Controller zu erstellen und zu übergeben als in der Form (nur um die Logik aus der Ansicht zu entfernen).


Original-Antwort (ich war so nah):

Nur um zu klären, Sie möchten, dass Ihre Bearbeitungsformular eine neue verschachtelte Anmeldung Notiz aufzunehmen (und ignorieren alle anderen bestehenden)? Ich habe nicht getestet, aber Sie sollten so tun können durch das Ersetzen:

<%= r.fields_for :registration_notes do |n| %> 

mit:

<%= r.fields_for @registration.registration_notes.build do |n| %> 

EDIT: Okay, von einem schnellen Test meiner eigenen, dass doesn‘ t Arbeit, sondern können Sie tun:

<%= r.fields_for :registration_notes do |n| %> 
    <%= n.text_area :content if n.object.id.nil? %> 
<% end %> 

Dies wird nur den Textbereich hinzufügen, wenn die ID des Registraturvermerk Null ist (dh es wurde noch nicht gespeichert.).

Auch ich dies tatsächlich getestet erste und es funktioniert;)

+0

Ich glaube, er will um eine neue Registrierung zu erstellen _note', die zum Objekt @registration gehört. – Huy

+0

Mein Verständnis war, dass er eine Notiz an die Bearbeitung angehängt haben möchte, so dass das Formular die Bearbeitung der Registrierung sowie das Erstellen einer neuen Registrierungsnotiz für einen Benutzer übernimmt, um verwandte Kommentare oder ähnliches zu hinterlassen. In diesem Fall würde ein separates Formular für die Note nicht funktionieren, würde es (wie es separat eingereicht werden müsste)? –

+0

Ahhh, vielleicht ist es das, was er will. :) – Huy

1

Wenn Sie ein neues Registrierungsformular für Ihre Bearbeitungsaktion erstellen möchten, können Sie einfach ein neues registration_note-Objekt instanziieren. Ihr Formular ist jetzt für das vorhandene Registrierungsobjekt.

Ich glaube, das ist, was Sie wollen:

class RegistrationsController < ApplicationController 
    def edit 
    @new_registration_note = RegistrationNote.new 
    @registration = Registration.find(params[:id]) 
    @registration.registration_notes.build 
    end 
end 

Ihrer Ansicht nach sollten Sie eine versteckte param übergeben, die die Registrierungsdatensatz-ID verweist:

<%= form_for @new_registration_note do |r| %> 
    <%= r.hidden_field :registration_id, :value => @registration.id %> 
    <%= r.text_area :content %> 
<% end %> 

Jetzt können Sie Ihre neu erstellen können Registrierungs-Hinweis, dass zu@registration gehört. Stellen Sie sicher, dass Sie eine Spalte in Ihrer registration_notes Tabelle haben, um auf die Registrierung zu verweisen. Sie können hier mehr über Assoziationen lesen: http://guides.rubyonrails.org/association_basics.html

1

Dank für Ihre Hilfe danken, wie ich in meinem Beitrag das einzige Problem mit dem Ansatz, sagte aus „Zaid Crouch“ (Ich glaube nicht, wissen, wie man einen Verweis auf einen Benutzer hehe) ist, dass, wenn das Formular Fehlerfelder hat das Formular wird klar und Boom nach dem Neuladen der Seite Sie nichts in Ihrem Formular gefüllt haben und können Sie sich vorstellen, wenn Sie wie 20 oder ist 30 Felder, die

Hier eine schreckliche Benutzererfahrung wäre natürlich ist meine Lösung, die bei der Validierung Modelle funktioniert:

class Registration < ActiveRecord::Base 
    attr_accessible :foo, :bar, :registration_notes_attributes 
    has_many :registration_notes 
    has_one :new_registration, class_name: 'RegistrationNote' 
    accepts_nested_attributes_for :new_registration 
end 

class RegistrationsController < ApplicationController 
    def edit 
    @registration = Registration.find(params[:id]) 
    @registration.build_new_registration 
    end 
end 

<%= form_for @registration do |r| %> 
    <%= r.text_field :foo %> 
    <%= r.text_field :bar %> 
    <%= r.fields_for :new_registration do |n| %> 
    <%= n.text_area :content %> 
    <% end %> 
<% end %> 

Ich verwende simple_form in meinem Beispiel, wenn Sie die gleiche Arbeit mit Validierungen und Transaktion einen Blick auf den gesamten Beitrag hier sehen wollen: http://elh.mx/ruby/using-simple_form-for-nested-attributes-models-in-a-has_many-relation-for-only-new-records/

0

Als Heriberto Perez richtig die Lösung in der am meisten darauf hingewiesen upvoted Die Antwort verwirft einfach alles, wenn ein Validierungsfehler in einem der Felder vorliegt.

Mein Ansatz ist ähnlich wie Heriberto ist aber doch ein bisschen anders:

Modell:

class Registration < ActiveRecord::Base 
    has_many :registration_notes 
    accepts_nested_attributes_for :registration_notes 

    # Because 0 is never 1 this association will never return any records. 
    # Above all this association don't return any existing persisted records. 
    has_many :new_registration_notes, -> { where('0 = 1') } 
            , class_name: 'RegistrationNote' 
    accepts_nested_attributes_for :new_registration_notes 
end 

Controller:

class RegistrationsController < ApplicationController 
    before_action :set_registration 

    def edit   
    @registration.new_registration_notes.build 
    end 

    private 

    def set_registration 
    @registration = Registration.find(params[:id]) 
    end 

    def new_registration_params 
    params.require(:registration).permit(new_registrations_attributes: [:content]) 
    end 
end 

Ausblick:

<%= form_for @registration do |r| %> 
    <%= r.text_field :foo %> 
    <%= r.text_field :bar %> 
    <%= r.fields_for :new_registration_notes do |n| %> 
    <%= n.text_area :content %> 
    <% end %> 
<% end %> 
Verwandte Themen