L'objectif de cet article est de créer le formulaire de saisie suivant.
Création d'une fonction pour enregistrer la recette et les ingrédients nécessaires à la recette ensemble dans la base de données
Étant donné que la recette et les ingrédients de la recette sont dans une relation parent-enfant, la structure de la table est la suivante. Parent: recettes Enfant: Ingrédients pour la recette (recette_ingrédients)
Nous effectuerons dans l'ordre suivant.
Installez jquery pour pouvoir utiliser cocoon avec rails6.
$ yarn add jquery
Modifier config / webpack / environment.js
config/webpack/environment.js
const { environment } = require('@rails/webpacker')
#Post-scriptum d'ici
const webpack = require('webpack')
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery'
})
)
#Postscript jusqu'à ici
module.exports = environment
Introduction de gemme
Gemfile
gem 'cocoon'
$ bundle install
Ajouter une bibliothèque
$ yarn add github:nathanvda/cocoon#c24ba53
Après l'exécution, vous pouvez effacer les deux éléments suivants. ・ L'application / assets / javascripts / cocoon.js a été créée -La description suivante a été ajoutée à package.json
package.json
"cocoon": "github:nathanvda/cocoon#c24ba53"
Enfin, ajoutez le contenu suivant à app / javascriptspacks / application.js
app/javascriptspacks/application.js
require('jquery')
import "cocoon";
La description qui n'est pas liée au contenu de cette implémentation est omise.
Créer un modèle
$ rails g model Recipe
$ rails g model RecipeIngredient
Modifier le fichier de migration
class CreateRecipes < ActiveRecord::Migration[6.0]
def change
create_table :recipes do |t|
t.string :name, null: false
t.timestamps
end
end
end
class CreateRecipeIngredients < ActiveRecord::Migration[6.0]
def change
create_table :recipe_ingredients do |t|
t.references :recipe, null: false, foreign_key: true
t.integer :ingredient_id, null: false
t.integer :quantity, null: false
t.timestamps
end
end
end
Effectuer la migration
$ rails db:migrate
Paramètres d'association
recipe.rb
class Recipe < ApplicationRecord
has_many :recipe_ingredients, dependent: :destroy
accepts_nested_attributes_for :recipe_ingredients
end
recipe_ingredient.rb
class RecipeIngredient < ApplicationRecord
belongs_to :recipe
end
accepts_nested_attributes_for Les données du modèle spécifié peuvent être incluses dans les paramètres sous forme de tableau. En d'autres termes, vous pourrez enregistrer ensemble les données des modèles recette et recette_ingrédients.
Créer un contrôleur
$ rails g controller recipes new create
Modifier le contenu du contrôleur
recipes_controller.rb
class RecipesController < ApplicationController
def new
@recipe = Recipe.new
@recipe_ingredients = @recipe.recipe_ingredients.build
end
def create
@recipe = Recipe.new(recipe_params)
if @recipe.save
redirect_to root_path
else
render action: :new
end
end
private
def recipe_params
params.require(:recipe).permit(:name, recipe_ingredients_attributes: [:id, :ingredient_id, :quantity, :_destroy])
end
end
Le modèle recette_ingredient spécifié dans accepte_nested_attributes_for, Je l'ai ajouté aux paramètres en tant que recette_ingredients_attributes: [] et je l'ai envoyé.
Comme pour le modèle, la description qui n'est pas liée au contenu de l'implémentation cette fois est omise.
ruby:recipes/new.html.erb
<%= form_with model: @recipe, url: '/recipes', method: :post, local: true do |f| %>
<!--Nom de la recette-->
<%= f.text_area :name %>
<!--Champ de saisie des ingrédients-->
<%= f.fields_for :recipe_ingredients do |t| %>
<%= render "recipes/recipe_ingredient_fields", f: t %>
<% end %>
<!--Bouton Ajouter des ingrédients-->
<%= link_to_add_association "ajouter à", f, :recipe_ingredients %>
<% end %>
fields_for Vous pourrez modifier différents modèles dans form_with.
ruby:recipes/_recipe_ingredient_fields.html.erb
<div class="nested-fields">
<%= f.collection_select(:ingredient_id, {}, :id, :name, {}) %>
<%= f.number_field :quantity %>
<div>Pièces</div>
<%= link_to_remove_association "Effacer", f %>
</div>
La zone délimitée par la balise div spécifiée par la classe nested-fields est la zone à ajouter / supprimer.
Faites attention au nom du modèle partiel à rendre. Une erreur se produira s'il ne s'agit pas de "_child model_fields.html.erb".
Je vous remercie pour votre travail acharné. Avec ce qui précède, je pense que vous pouvez créer un formulaire de saisie dynamique.
Introduction de cocoon dans Rails 6 Configurez un joyau cocon qui peut implémenter de manière concise des formulaires imbriqués dans un environnement Webpack
A propos de la création d'un formulaire de saisie dynamique [Rails] Comment enregistrer plusieurs données dans une table de relations parent-enfant en même temps à l'aide de cocoon
À propos de fields_for Comment bien utiliser fields_for