[RUBY] [Rails] Pourquoi est-il rendu si la sauvegarde réussit et que redirect_to échoue?

introduction

Pendant le développement avec Rails, je m'inquiétais de la manière de gérer le rendu lors de l'implémentation du formulaire, j'ai donc pu reconfirmer la différence entre redirect_to et render lors de l'enquête, je vais donc le laisser comme un rappel. En passant, j'écrirai aussi que je m'inquiétais du rendu pendant un moment. (Plus précisément, gestion avant_action)

environnement

・ Rubis 2.6.5 ・ Rails 6.0.3

Statut

J'ai fait une demande d'enregistrement des informations du restaurant et défini les actions suivantes sur le contrôleur.

shops_controller.rb


 def new
    @shop = Shop.new
 end

 def create
    @shop = @owner.shops.new(shop_params)
    if @shop.save
      redirect_to :index
    else
      render :new
    end
  end

J'ai écrit ceci sans plus réfléchir, mais si la sauvegarde échoue, pourquoi utiliser render pour revenir au formulaire de publication? Revenons là-dessus.

** En conclusion, je souhaite revenir à nouveau au formulaire de saisie tout en conservant le contenu d'entrée **.

Alors, pourquoi cela peut-il être réalisé en utilisant render au lieu de redirect_to? Revenons au comportement de redirect_to et render.

Qu'est-ce que redirect_to

** redircet_to est un processus qui permet au côté client d'accéder à l'action (ou au chemin) spécifié. ** ** En conséquence, vous accéderez à la page après avoir revisité le flux de MVC. Plus précisément, le flux est "accéder à nouveau à l'action spécifiée ⇨ exécuter l'action du contrôleur ⇨ afficher la vue correspondante".

Cela fait exactement la même chose que d'accéder à la vue d'action à partir de l'URL.

Qu'est-ce que le rendu

Render, par contre, affiche simplement la vue correspondant à l'action spécifiée sans passer par l'action ** à nouveau. ** ** Contrairement à redirect_to, il renvoie la vue sans exécuter le contenu de la nouvelle action.

La raison pour laquelle le contenu d'entrée est conservé par render

Jetons à nouveau un coup d'œil au code en fonction de l'explication ci-dessus.

shops_controller.rb


 def new
    @shop = Shop.new
 end

 def create
    @shop = @owner.shops.new(shop_params)
    if @shop.save
      redirect_to :index
    else
      render :new
    end
  end

Puisque la nouvelle action est une nouvelle page d'inscription pour les informations sur la boutique, @ shop = Shop.new est défini dans l'action. (Créer une instance vide) Après cela, la valeur saisie dans le formulaire est transmise en tant que paramètres, et elle peut être enregistrée en la transmettant avec succès en tant qu'information de @shop créée cette fois par l'action de création.

Si l'enregistrement échoue (dans le cas de else), il sera de nouveau renvoyé au formulaire, mais si ** redirect_to est utilisé à ce moment, la nouvelle action sera exécutée à nouveau et @shop redeviendra une instance vide. ** **

En revanche, si vous utilisez ** render, la nouvelle action n'est pas utilisée, donc @shop affichera à nouveau la vue formulaire tout en conservant les valeurs des paramètres reçus par l'action de création. ** **

haml:new.html.haml



.shop-wrapper
  = form_with model: [@owner, @shop], html: {class: "shopform"}, local: true do |f|

Ce qui précède est un extrait de la vue, mais comme le formulaire reçoit @owner et @shop et affiche le contenu, si le @shop a du contenu, il affichera le contenu correctement.

C'est pourquoi vous devez utiliser le rendu lorsque l'action de création échoue.

L'erreur que j'ai rencontrée cette fois

À propos, lorsque j'ai défini le rendu cette fois, j'ai rencontré pour la première fois l'erreur suivante. スクリーンショット 2020-06-26 21.45.44.png

Pendant un moment, cela s'est produit, mais j'ai défini le before_aciton suivant pour la nouvelle action.

shops_controller.rb



before_action :set_select_lists, only: [:new]

#Omission

private
def set_select_lists
    @stations = Station.all.map {|station| [station.name, station.id] }.unshift(["Veuillez choisir parmi les suivants", nil])
    @genres = Genre.all.map {|genre| [genre.name, genre.id] }.unshift(["Veuillez choisir parmi les suivants(Obligatoire)", nil])
    @marks =  Mark.all.map {|mark| [mark.favorite, mark.id] }.unshift(["Veuillez choisir parmi les suivants(Obligatoire)", nil])
  end

J'ai créé une liste de sélection déroulante dans le formulaire et l'ai définie avec before_action.

Comme je l'ai écrit précédemment, le rendu ne passe pas à nouveau par la nouvelle action, donc ** before_action n'est pas effectué → Il n'y a pas de valeur définie et une erreur se produit dans l'affichage de la vue **.

En réponse à cela, pendant un moment, j'ai pensé: "S'il y a une variable que je dois définir de manière inattendue chez @shop, puis-je utiliser render?", Mais après avoir réfléchi pendant quelques minutes, je l'ai résolue immédiatement.

Réécrivez l'action de création comme suit.

shops_controller.rb


def create
    @shop = @owner.shops.new(shop_params)
    if @shop.save
    else
      set_select_lists
      render :new
    end
  end

En exécutant set_select_lists qui a été fait dans before_action avant le rendu avec l'action de création, vous pouvez effectuer le rendu avec la valeur également acquise (le rendu effectue uniquement l'action de création, puis crée une nouvelle vue. Parce qu'il est affiché)

Pour un moment? ?? ?? Mais ce n'était pas une histoire si compliquée.

À la fin

En fait, le comportement de redirect_to et render a été l'endroit où j'ai touché pour la première fois à la programmation avec Progate et a été le plus perturbé depuis environ un mois. Quand j'ai remarqué la différence ici, j'ai eu l'image que ma compréhension de MVC s'est approfondie en même temps.

J'espère que cela sera utile pour les débutants comme moi.

Recommended Posts

[Rails] Pourquoi est-il rendu si la sauvegarde réussit et que redirect_to échoue?
[rails] Différence entre redirect_to et render
[Rails] Différence entre redirect_to et render [Débutant]
Les rails rendent redirect_to
[Rails] Afficher le message d'erreur - Différence entre render et redirect_to, flash-
[Rails] Quelle est la différence entre la redirection et le rendu?
[Rails] Différentes différences entre redirect_to et méthode de rendu et méthode de sortie de la méthode de rendu
Les rails sont difficiles et douloureux!
Les rails sont difficiles et douloureux! Ⅱ
Différence entre render et redirect_to
Différence entre render et redirect_to
[Rails] Enregistrer l'heure de début et l'heure de fin
Divisez par Ruby! Pourquoi est-ce 0?
Utilisez redirect_to et effectuez un rendu correctement