Il existe des tables avec divers éléments enfants tels que «@ comment» et «@ employee» associés à «@ shop». Au moment de l'enregistrement initial des informations, j'ai pu enregistrer tous les éléments enfants avec l'élément parent tel que @ shop
, @ comment
, @ employee
, mais
Bien que j'aie réalisé cela en utilisant ʻaccepts_nested_attributes_for` sous la forme de l'article ci-dessous,
▼ C'était réalisé comme ça Créer des données de table enfant à la fois avec fields_for (j'écris également un test) [Rails] [Rspec]
Parmi ceux-ci, l'édition de formulaires uniquement pour «@ shop» et la publication / modification de formulaires tels que «@ comment» et «@ employé» sont devenues nécessaires, de sorte que le «modèle» s'est progressivement gonflé de diverses descriptions.
↑ Dans la situation ci-dessus, form_object
peut simplifier la description du modèle en rassemblant les validations et les paramètres de valeur par défaut liés à un formulaire spécifique en un seul endroit. Personnellement, je suis tombé sur l'introduction, alors je vais écrire un article et en garder une trace.
L'environnement d'exécution est le suivant.
La manière de base d'écrire form_object
, controller
et view
est la suivante. Cette fois, je voudrais prendre un exemple de formulaire qui vous permet d'enregistrer un @ commentaire
lors de votre première inscription @ shop
.
Cet article a été le plus utile pour la mise en œuvre.
Enregistrer plusieurs enregistrements enfants sans accepte_nested_attributes_for
shops | |
---|---|
name | string |
category | integer |
La catégorie ↑ est le type de boutique. Colonne ʻEnum`.
comments | |
---|---|
content | text |
shop_id | integer |
form_object
/forms/shop_entry_form.rb
class ShopEntryForm
include ActiveModel::Model
# @Description de la boutique-----------------------------
concerning :ShopBuilder do
def initialize(params = {})
super(params)
@category = params[:category]
end
def facility
@shop ||= Shop.new
end
end
attr_accessor :name, :category
validates :name, presence: true
validates :category, presence: true
# @Description du commentaire-----------------------------
concerning :CommentBuilder do
attr_reader :comments_attributes
def comments
@comments_attributes ||= Comment.new
end
def comments_attributes=(attributes)
@comments_attributes = Comment.new(attributes)
end
end
attr_accessor :content
#Logique de mise en œuvre------------------------------------
def save
#S'il y a une erreur de validation, false est renvoyé et le traitement suivant n'est pas effectué.
return false if invalid?
shop.assign_attributes(shop_params)
build_asscociation
shop.save ? true : false
end
private
def shop_params
{
name: name,
category: @category,
}
end
def build_asscociations
#Ajoutez un commentaire à l'élément enfant de la boutique. Cependant, si le contenu est vide, il ne sera pas ajouté.
shop.comments << comments if comments[:content].present?
end
end
Il y avait beaucoup de pierre d'achoppement avec cela seul. .. .. .. Premièrement, la partie «concernant: ShopBuilder do ... end» a la signification suivante.
#Cette description est...
concern :ShopBuilder do
...
end
#Identique à ci-dessous
module ShopBuilder
extend ActiveSupport::Concern
...
end
Pour plus de détails, consultez Cet article auquel j'ai fait référence lors de la mise en œuvre.
Ensuite, la partie de ʻinitialize (params = {}) ... end` a la signification suivante.
def initialize(params = {})
# @Rendre les paramètres de la boutique accessibles
super(params)
#Description des colonnes pour lesquelles les valeurs par défaut sont définies dans DB
@category = params[:category]
end
Tout d'abord, concernant super (params)
, selon l'article suivant, qui était également un article très utile pour la mise en œuvre.
Utiliser la classe de formulaire
Une description qui stocke les paramètres avec super (params)
, et a la même signification que la description suivante.
@attributes = self.class._default_attributes.deep_dup
assign_attributes(params)
En outre, les colonnes pour lesquelles les valeurs par défaut sont définies du côté de la base de données ne peuvent pas accéder aux paramètres à moins que vous n'écriviez explicitement pour accéder aux paramètres comme indiqué ci-dessous. Il est devenu ... ** **
@category = params[:category]
Ce mystère ne peut être résolu. Je voudrais en faire un prochain numéro. .. .. La raison pour laquelle la valeur par défaut est requise du côté db pour les colonnes utilisant enum est [cet article](https://framgia.com/journal/rails%E3%81%AEenum-%E8%AB%B8%E5% Voir 88% 83% E3% 81% AE% E5% 89% A3% EF% BC% 88% EF% BC% 91% EF% BC% 89-% E3% 80% 80from-viblo /).
Et la partie de def comments_attributes = (attributes) ... end
,
def comments_attributes=(attributes)
@comments_attributes = Comment.new(attributes)
end
C'est une façon d'écrire méthode setter
que vous voyez rarement si vous ne faites que des Rails, et vous pouvez changer l'élément avec l'argument @ by ** sous la forme de méthode (argument)se terminant par
= Je vais.
Personnellement, je pense que c'est proche de l'image de faire quelque chose comme ça.
def comments_attributes=(attributes) # ...Ce qui suit est omis
#Une telle image
comments_attributes = attributes
#Donc tu peux l'appeler comme ça
self.comments_attributes
# =>Contenu des attributs
C'est parce que je n'ai pas compris correctement les getters et les setters Ruby. .. .. .. Tohoho. .. .. Je ferai de mon mieux. .. .. Pour la méthode se terminant par `=, voir " Introduction à Ruby pour les professionnels, des spécifications du langage aux techniques de développement / débogage pilotées par les tests " J'ai relu "p215" de /) environ 15 fois.
controller
Ce qui suit est une description du contrôleur. Le contrôleur ressemble à ceci.
app/controllers/shops_controller.rb
class ShopsController < ApplicationController
def new
@shop = ShopEntryForm.new
end
def create
@shop = ShopEntryForm.new(shop_entry_params)
if @shop.save
#Que faire quand ça réussit
else
#Que faire en cas d'échec
end
end
private
def shop_entry_params
params.require(:shop_entry_form).permit(:caregory,
:name,
comments_attributes: [:content])
end
end
J'ai l'impression que la description n'a pas diminué de façon inattendue. Au début, je m'attendais à ce que shop_entry_params
soit réduit du contrôleur, mais je ne pouvais pas le supprimer du contrôleur après tout. Seule la méthode qui crée l'association peut être supprimée du contrôleur.
En ce qui concerne le modèle, ** les méthodes de validation et de définition des valeurs par défaut, les associations, etc. ont toutes été supprimées! ** Aucune description supplémentaire! !! Après tout, form_object
est un moyen pratique d'écrire un modèle mince! !!
View Enfin, la vue ressemble à ceci.
haml:app/views/shops/new.html.haml
= form_with model: @shop, url: shops_path, local: true do |f|
= f.text_field :name
= f.fields_for :shop_comments, local: true do |comment_form|
= comment_form.text_field
= f.submit "Envoyer"
L'utilisation de fields_for
est identique à l'implémentation utilisant ʻaccept_nested_attributes_for` ^^
Le test était également très simple!
spec/forms/shop_entry_form_spec.rb
require 'rails_helper'
RSpec.describe ShopEntryForm, type: :model do
before do
@shop_form = ShopEntryForm.new(category: "category1", name: "Atelier de test")
end
describe "Test de validation" do
it "Passez la validation si vous avez un nom et une catégorie" do
@shop_form.valid?
expect(@shop_form).to be_valid
end
#Ce qui suit est omis
end
end
Tout ce que j'avais à faire était de faire attention à l'emplacement du fichier, à la partie RSpec.describe ShopEntryForm ...
, et à la description lors de la création de l'instance de test ^^
C'est un peu vieux, mais je l'ai créé en référence à cet article.
Ecrire un test d'un objet de formulaire avec RSpec
Eh bien, la mise en œuvre a été très longue. La forme réelle avait trois types d'éléments enfants imbriqués, et la forme était assez compliquée, mais surtout, je pense que c'était parce que je n'étais pas habitué à écrire du Ruby brut. .. .. Quand je me calmerai, j'aimerais revoir Ruby.
Ceci est un résumé des articles et des documents auxquels j'ai fait référence cette fois.
▼ Rédaction générale Enregistrer plusieurs enregistrements enfants sans accepte_nested_attributes_for
▼ Comment accéder aux paramètres Utiliser la classe de formulaire «Introduction à Ruby pour les professionnels, des spécifications de langage aux techniques de développement et de débogage pilotées par les tests» (p.215)
▼ À propos de Bite-sized separation of concerns
▼ Comment rédiger un test Ecrire un test d'un objet de formulaire avec RSpec
Après cela, les formulaires d'édition et de mise à jour restent également, donc j'aimerais travailler dessus ^^
Recommended Posts