・ Serveur Ubuntu Cloud9 ・ Rails 6.0.0 ・ Ruby 2.6.3p62 (révision 67580 du 16/04/2019) [x86_64-linux]
Supposons que vous ayez un modèle Parent et un modèle Kid avec des relations un-à-plusieurs comme ceci:
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
end
models/kid.rb
class Kid < ApplicationRecord
belongs_to :parent
end
Puisque les données du modèle enfant sont enregistrées en même temps que les données du modèle parent sont enregistrées, accepts_nested_attributes_for
Vers le modèle Parent.
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
accepts_nested_attributes_for :kids
end
Cela vous permet d'utiliser des formulaires imbriqués qui vous permettent d'enregistrer les données associées dans un seul formulaire.
Ensuite, dans le contrôleur Parents du modèle parent, créez une instance vide qui reçoit les paramètres envoyés depuis la page de formulaire.
Il crée également une instance vide du modèle enfant associé. Aussi dans le paramètre fort pour recevoir les landaus du modèle enfant
kids_attributes: [:name, :age, :toy]
Passe.
#### **`controllers/parents_controller.rb`**
```rb
class ParentsController < ApplicationController
#(Omis)
def new
@parent = Parent.new
@parent.kids.build #Créer une instance vide du modèle enfant
end
def create
@parent = Parent.new(parent_params)
if @parent.save
redirect_to root_url
else
render :new
end
end
#(Omission)
private
def parent_params
#Vous permet de recevoir des paramètres pour les modèles enfants
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">Inscription des parents</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>
<!--Formulaire imbriqué pour recevoir des données pour les modèles enfants-->
<%= f.fields_for :kids do |kf| %>
<h1 class="text-center">Inscription des enfants</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 "Inscrivez-vous avec le contenu ci-dessus", class: "btn btn-primary btn-lg btn-block" %>
</div>
<% end %>
</div>
</div>
C'est difficile à voir car il contient la classe Bootstrap, mais le `` f.fields_for '' ci-dessus est le formulaire qui reçoit les données du modèle enfant.
Bien qu'il s'agisse d'un formulaire de saisie pour les modèles enfants, en créant plusieurs instances vides, vous pouvez augmenter le nombre de champs de saisie sans augmenter la forme de vue elle-même. Par exemple, en modifiant le contrôleur Parents comme suit, un ensemble de formulaires d'entrée de modèle enfant peut être affiché lors de l'enregistrement nouvellement, et deux ensembles de formulaires d'entrée de modèle enfant peuvent être affichés lors de la mise à jour.
controllers/parents_controller.rb
class ParentsController < ApplicationController
#(Omission)
def new
@parent = Parent.new
@parent.kids.build #Créer une instance vide du modèle enfant
end
def create
@parent = Parent.new(parent_params)
if @parent.save
redirect_to root_url
else
render :new
end
end
#(Omission)
def edit
@parent = Parent.find(params[:id])
@parent.kids.build #Créer une instance vide du modèle enfant
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
En créant également une instance vide du modèle enfant dans l'action d'édition, les "données de modèle enfant enregistrées" + 1 formulaire d'entrée seront créés au moment de la mise à jour.
Cela rend plus facile d'augmenter le nombre de formulaires d'entrée que de les ajouter dynamiquement avec JS. (Le goulot d'étranglement est que le nombre est limité ...)
Si vous souhaitez ajouter plus de formulaires, vous pouvez créer plus d'instances vides.
@parent.kids.build
De
#### **`n.times { @parent.kids.build }`**
Ce faisant, vous pouvez générer n formulaires d'entrée.
Cependant, en l'état, les données vides seront enregistrées si le formulaire ajouté n'est pas rempli.
Pour éviter cela, passez le Proc suivant comme deuxième argument de accepts_nested_attributes_for
ajouté au modèle Parent.
models/parent.rb
class Parent < ApplicationRecord
has_many :kids, dependent: :destroy
accepts_nested_attributes_for :kids, reject_if: lambda {|attributes| attributes['name'].blank?}
end
Dans le cas ci-dessus, si le nom du formulaire de saisie du modèle enfant est vide, tous les autres attributs (ici, âge, jouet) ne seront pas enregistrés même s'ils sont saisis.
Si vous ne souhaitez pas vous inscrire si le nom ou l'âge n'est pas entré, changez comme suit.
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
En plus de ce qui précède, vous pouvez contrôler librement les valeurs stockées en modifiant la validation sur le modèle enfant.
En plus de cela, il peut y avoir des cas où vous souhaitez supprimer uniquement les données du modèle enfant associé, mais pour plus de détails, voir «Action View Form Helper» dans le Guide Rails. Ce sera utile.
Je suis Tatsuron, un débutant qui apprend actuellement Ruby on Rails. J'ai publié des articles sur les fonctionnalités bloquées pendant plusieurs jours lors de la création de ma propre application. Si vous avez des erreurs ou des conseils, veuillez commenter.