・ Cloud9 Ubuntu Server ・ Schienen 6.0.0 ・ Ruby 2.6.3p62 (16.04.2019, Revision 67580) [x86_64-linux]
Angenommen, Sie haben ein Elternmodell und ein Kindermodell mit Eins-zu-Viele-Beziehungen wie folgt:
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
end
models/kid.rb
class Kid < ApplicationRecord
belongs_to :parent
end
Da die Daten des untergeordneten Modells gleichzeitig mit den Daten des übergeordneten Modells gespeichert werden, akzeptiert `` `akzeptierte_verschachtelte_Attribute_für``` Zum übergeordneten Modell.
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
accepts_nested_attributes_for :kids
end
Auf diese Weise können Sie verschachtelte Formulare verwenden, mit denen Sie die zugehörigen Daten in einem Formular registrieren können.
Erstellen Sie als Nächstes im übergeordneten Controller des übergeordneten Modells eine leere Instanz, die die von der Formularseite gesendeten Parameter empfängt.
Außerdem wird eine leere Instanz des zugeordneten untergeordneten Modells erstellt. Auch im starken Parameter, um die Kinderwagen des untergeordneten Modells zu erhalten
kids_attributes: [:name, :age, :toy]
Geht vorbei.
#### **`controllers/parents_controller.rb`**
```rb
class ParentsController < ApplicationController
#(Weggelassen)
def new
@parent = Parent.new
@parent.kids.build #Erstellen Sie eine leere Instanz des untergeordneten Modells
end
def create
@parent = Parent.new(parent_params)
if @parent.save
redirect_to root_url
else
render :new
end
end
#(Unterlassung)
private
def parent_params
#Ermöglicht den Empfang von Parametern für untergeordnete Modelle
params.require(:parent).permit(
:name, :age, kids_attributes: [:name, :age, :toy]
)
end
end
erb:new.html.erb
<div class="container">
<div class="col-sm-10 col-sm-offset-1">
<h1 class="text-center">Elternregistrierung</h1>
<%= form_with(model: @parent, local: true) do |f| %>
<div class="field form-group">
<%= f.label :name %>
<%= f.text_field :name, class: "form-control" %>
</div>
<div class="field form-group">
<%= f.label :age %>
<%= f.number_field :age, class: "form-control" %>
</div>
<!--Verschachteltes Formular zum Empfangen von Daten für untergeordnete Modelle-->
<%= f.fields_for :kids do |kf| %>
<h1 class="text-center">Kinderregistrierung</h1>
<div class="field form-group">
<%= kf.label :name %>
<%= kf.text_field :name, class: "form-control" %>
</div>
<div class="field form-group">
<%= kf.label :age %>
<%= kf.number_field :age, class: "form-control" %>
</div>
<div class="field form-group">
<%= kf.label :toy %>
<%= kf.text_field :toy, class: "form-control" %>
</div>
<% end %>
<div class="field form-group">
<%= f.submit "Registrieren Sie sich mit den oben genannten Inhalten", class: "btn btn-primary btn-lg btn-block" %>
</div>
<% end %>
</div>
</div>
Es ist schwer zu erkennen, da es die Bootstrap-Klasse enthält, aber das obige `` `f.fields_for``` ist das Formular, das die Daten des untergeordneten Modells empfängt.
Obwohl es sich um ein Eingabeformular für untergeordnete Modelle handelt, können Sie durch Erstellen mehrerer leerer Instanzen die Anzahl der Eingabefelder erhöhen, ohne die Ansichtsform selbst zu erhöhen. Wenn Sie beispielsweise den Eltern-Controller wie folgt ändern, können bei der Neuregistrierung ein Satz untergeordneter Modelleingabeformulare angezeigt werden, und beim Aktualisieren können zwei Sätze untergeordneter Modelleingabeformulare angezeigt werden.
controllers/parents_controller.rb
class ParentsController < ApplicationController
#(Unterlassung)
def new
@parent = Parent.new
@parent.kids.build #Erstellen Sie eine leere Instanz des untergeordneten Modells
end
def create
@parent = Parent.new(parent_params)
if @parent.save
redirect_to root_url
else
render :new
end
end
#(Unterlassung)
def edit
@parent = Parent.find(params[:id])
@parent.kids.build #Erstellen Sie eine leere Instanz des untergeordneten Modells
end
def update
@parent = Parent.find(params[:id])
if @parent.update(parent_params)
redirect_to root_url
else
render :edit
end
end
def destroy
@parent = Parent.find(params[:id])
@parent.destroy
redirect_to root_url
end
private
def parent_params
params.require(:parent).permit(
:name, :age, kids_attributes: [:name, :age, :toy]
)
end
end
Durch Erstellen einer leeren Instanz des untergeordneten Modells in der Bearbeitungsaktion werden zum Zeitpunkt der Aktualisierung "registrierte untergeordnete Modelldaten" + 1 Eingabeformular erstellt.
Dies macht es einfacher, die Anzahl der Eingabeformulare zu erhöhen, als sie dynamisch mit JS hinzuzufügen. (Der Engpass ist, dass die Anzahl begrenzt ist ...)
Wenn Sie weitere Formulare hinzufügen möchten, können Sie weitere leere Instanzen erstellen.
@parent.kids.build
Von
#### **`n.times { @parent.kids.build }`**
Auf diese Weise können Sie n Eingabeformulare generieren.
So wie es ist, werden leere Daten gespeichert, wenn das hinzugefügte Formular nicht ausgefüllt wird. Um dies zu verhindern, übergeben Sie den folgenden Proc an das zweite Argument von `` `accept_nested_attributes_for```, das dem übergeordneten Modell hinzugefügt wurde.
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
accepts_nested_attributes_for :kids, reject_if: lambda {|attributes| attributes['name'].blank?}
end
Wenn im obigen Fall der Name des Eingabeformulars für das untergeordnete Modell leer ist, werden alle anderen Attribute (hier Alter, Spielzeug) nicht gespeichert, selbst wenn sie eingegeben werden.
Wenn Sie sich nicht registrieren möchten, wenn Name oder Alter nicht eingegeben wurden, ändern Sie dies wie folgt.
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
accepts_nested_attributes_for :kids, reject_if: lambda {|attributes| attributes['name'].blank? || attributes['age'].blank?}
end
Darüber hinaus können Sie die gespeicherten Werte frei steuern, indem Sie die Validierung in das untergeordnete Modell ändern.
Darüber hinaus kann es Fälle geben, in denen Sie nur die Daten des zugeordneten untergeordneten Modells löschen möchten. Weitere Informationen finden Sie im Rails-Handbuch unter "Action View Form Helper". Es wird hilfreich sein.
Ich bin Tatsuron, ein Anfänger, der gerade Ruby on Rails lernt. Ich habe über die Funktionen geschrieben, die beim Erstellen meiner eigenen App mehrere Tage lang hängen geblieben sind. Wenn Sie Fehler oder Ratschläge haben, kommentieren Sie bitte.
Recommended Posts