Comment transmettre des erreurs de forme en session ou flash? [Rails 2.3.5]
-
24-09-2019 - |
Question
J'ai action pour créer une forme qui génère potentiellement des erreurs (à savoir le prénom est manquant) et redirige ensuite.
Le problème est que lorsque la redirection se forme les erreurs se perdent. Comment pourrais-je passer ces erreurs de forme dans une session à afficher de nouveau sous la forme d'origine (qui doit encore être rempli avec les détails précédents, comme dans le comportement error_messages d'origine)?
Merci!
Le code:
def create
@contact = Contact.new(params[:contact])
if @contact.save
flash[:notice] = "Sent."
else
flash[:notice] = "Error."
end
end
La solution
Ceci est un problème délicat que j'ai eu du mal avec moi-même. La première question que je voudrais poser est pourquoi avez-vous besoin de rediriger lorsque des erreurs sont trouvées? vous obligeant à rendre l'action quand il y a des erreurs a été une décision consciente des concepteurs du cadre Rails en raison de problèmes de complexité et de la convivialité.
Voici le gros problème, donc dans votre action, vous créez une instance d'un modèle à l'aide params, la validation de l'objet tombe en panne et que vous décidez de rediriger vers une autre action. Avant de rediriger vers une autre action que vous auriez à enregistrer l'état actuel de votre instance de modèle à la session et rediriger vers l'action: foo. Dans l'action: foo vous auriez à mettre à jour les essayer de nouveau attributs et de transmettre les erreurs à la vue par une variable d'instance. Le problème ici est que vous couplant des actions dans votre contrôleur qui est une mauvaise chose (une action est dépendante de l'autre). Il y a une foule d'autres problèmes que je pouvais taper à propos pour toujours, mais si vous avez seulement besoin de faire cela pour une seule ressource, voici comment je le ferais:
config / routes.rb
map.resources :things, :member => { :create_with_errors => :get }
things_controller.rb
def new
@thing = Thing.new
end
def create
@thing = Thing.create(params[:thing])
if @thing.save
redirect_to things_path
else
session[:thing] = @thing
redirect_to create_errors_thing_path(@thing)
end
end
def create_with_errors
@thing = session[:thing]
@errors = @thing.errors
render :action => :new
end
app / views / choses / new.html.erb
<% if defined?(@errors) %>
<% #do something with @errors to display the errors %>
<% end %>
<!-- render the form stuff -->
Je sais ce que vous pensez ... c'est hideux. Croyez-moi, je l'ai fait beaucoup de tentatives pour résoudre ce problème et je suis venu à réaliser, le mécanisme des rails développeurs ont choisi est le meilleur et le plus facile de traiter avec des erreurs.
Autres conseils
La convention Rails est de rendre le point de vue de l'action initiale plutôt que de faire une redirection. Donc, votre code ressemblera à ceci:
def create
@contact = Contact.new(params[:contact])
if @contact.save
flash[:notice] = 'Sent.'
redirect_to @contact
else
flash.now[:notice] = 'Error.'
render :new
end
end
En cas de configuration supplémentaire nécessaire à faire pour l'action new
, extraire le code commun dans une méthode privée et l'appeler dans un before_filter
pour les new
et create
.