127 votes

rails - Concevoir - Manutention - devise_error_messages

dans mon utilisateur de modifier la page, il y a une ligne comme suit:

<%= devise_error_messages! %>

Le problème est que ce n'est pas les erreurs de sortie du stand manière que le reste de l'application:

<% flash.each do |key, value| %>
    <div class="flash <%= key %>"><%= value %></div>
<% end %>

Ma question est comment puis-je obtenir le concevoir message d'erreur de travailler comme les autres que l'utilisation du flash.chaque?

Merci

135voto

John Points 4635

J'essaie de comprendre moi-même. Je viens de trouver cette question enregistré sur Github https://github.com/plataformatec/devise/issues/issue/504/#comment_574788

José est à dire qu' devise_error_messsages! méthode n'est qu'un stub (même si elle contient de la mise en œuvre) et que nous sommes censés remplacer/remplacer. Il aurait été agréable si cela a été souligné, quelque part dans le wiki, c'est pourquoi je pense qu'il y a quelques personnes comme nous qui ont été dans le doute.

Donc, je vais essayer de la réouverture du module et de redéfinir la méthode, de manière efficace en remplaçant la valeur par défaut de mise en œuvre. Je vais vous laisser savoir comment ça se passe.

Mise à jour

Yep, ça marche. J'ai créé app/helpers/devise_helper.rb et l'a remplacée comme suit:

module DeviseHelper
  def devise_error_messages!
    'KABOOM!'
  end
end

Donc, sachant cela, je peux modifier la méthode pour afficher les messages d'erreur de la façon dont je le veux.

Pour vous aider à résoudre votre problème d'origine: c'est Ici l'original de l' devise_helper.rb sur Github. Jetez un oeil à la façon dont les messages d'erreur sont traversées:

messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join

Qui devrait vous aider à obtenir commencé. :)

Une autre mise à jour

L' resource objet est en fait le modèle qui est utilisé par les concevoir (allez comprendre).

resource.class         #=> User
resource.errors.class  #=> ActiveModel::Error

Il semble également être définie dans une étendue supérieure (probablement en provenance de l'automate), de sorte qu'il peut être consulté dans une variété d'endroits.

N'importe où dans votre Helper

module DeviseHelper
  def devise_error_messages1!
    resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
  end

  def devise_error_messages2!
    resource.errors.full_messages.map { |msg| content_tag(:p, msg) }.join
  end
end

Votre Point De Vue

<div><%= resource.errors.inspect %></div>

38voto

Lukasz Muzyka Points 642

Ci-dessous la solution fonctionne avec la dernière concevoir dès maintenant (3.2.2) et les Rails 4.0.2. Mais c'est tellement simple que je ne vois pas la raison pourquoi ne serait-il pas un travail de 10 ans à partir de maintenant;)

Si vous souhaitez recycler vos messages d'erreur et leur demander de regarder la même dans l'ensemble de votre application que je recommande quelque chose comme ceci (j'ai appris avec Michael Hartl tut):

Créer partielle pour les messages d'erreur: layouts/_error_messages.html.erb Mis à l'intérieur de code suivant (ici j'utilise bootstrap 3 classes):

<% if object.errors.any? %>
  <div id="error_explanation">
    <div class="alert alert-danger alert-dismissable">
      <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
      <p><strong>This form contains <%= pluralize(object.errors.count, 'errors') %>.</strong></p>
      <ul>
        <% object.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  </div>
<% end %>

Maintenant vous avez quelque chose recyclables et vous pouvez les utiliser à travers le conseil d'administration. Au lieu de la norme de concevoir:

<%= devise_error_messages! %>

L'appeler dans votre formulaire, comme ceci:

<%= render 'layouts/error_messages', object: resource %>

Vous pouvez le mettre dans n'importe quelle forme. Au lieu de passer concevoir des ressources vous pouvez passer des variables à partir de votre formulaire comme ceci:

<%= form_for @post do |f| %>
  <%= render 'layouts/error_messages', object: f.object %>  
  <%= f.text_field :content %>
  <%= f.submit %>
<% end %>

22voto

Eric Hu Points 7388

Je sais que ça a été un moment depuis que cette question a été posté, mais je voulais juste commenter ce que j'ai trouvé. Les deux personnes qui ont déjà répondu ont été d'une grande aide pour moi et j'ai juste voulu contribuer.

Vous verrez tout au long de Concevoir qu'il y a des appels à l'aide de render_with_scope. Je crois que c'est une méthode définie par concevoir et s'applique essentiellement de la portée actuelle de la fenêtre de rendu.

Pourquoi est-ce pertinent? Concevoir contient vos erreurs dans resource.errors (pas @resource.errors). Concevoir fonctionne très bien si vous voulez utiliser la sortie de la boîte, pour ainsi dire.

Les problèmes liés à ces erreurs surviennent si vous commencez à changer votre utilisateur de gestion du comportement. Par l'ajout d'un redirect_to ou render (au lieu de render_with_scope) où Concevoir auparavant n'en avais pas, vous êtes essentiellement en lançant les messages d'erreur. Cela fait de Concevoir hostile à la modification, à mon avis.

Ma solution est-ce

# In application.html.erb
<% flash.each do |name, msg| %>

  # New code (allow for flash elements to be arrays)
  <% if msg.class == Array %>
    <% msg.each do |message| %>
      <%= content_tag :div, message, :id => "flash_#{name}" %>
    <% end %>
  <% else %>

    # old code
    <%= content_tag :div, msg, :id => "flash_#{name}" %>

  <% end %> #don't forget the extra end
<% end %>

et

# Wherever you want Devise's error messages to be handled like 
# your other error messages
# (in my case, registrations_controller.rb, a custom controller)
flash[:notice] = flash[:notice].to_a.concat resource.errors.full_messages

Le dernier bloc de code prend Concevoir de messages d'erreur comme un tableau et l'ajoute à l' flash[:notice] (comme un tableau). Chaque message sera imprimé une ligne à la fois. Si j'ai le temps, je pense que je vais changer la façon de Concevoir les poignées des messages d'erreur pour ce faire, tout au long de mon application, il semble beaucoup plus propre d'avoir un message d'erreur système au lieu de deux.

12voto

Kulgar Points 736

Je veux juste apporter un petit nouveau ici:

J'ai donc trouvé un moyen plus facile d'obtenir le résultat que "AnApprentice" voulait.

Tout d'abord, si vous souhaitez personnaliser quoi que ce soit dans le dispositif plug-in, je conseille vivement la copie d'après le code de "\Ruby_repertory\lib\ruby\gemmes\1.9.1\gemmes\concevoir-version\app\controllers|helpers|expéditeurs..." le fichier que vous voulez dans votre projet.

[Edit] Ou vous pouvez créer votre fichier d'hériter de la "normale" concevoir de fichiers...... Comme dire... Vous voulez remplacer une seule fonction au sein de l'concevoir/registrations_controller.rb, la première ligne de vos Utilisateurs personnalisée d'enregistrements contrôleur serait:

class Users::RegistrationsController < Devise::RegistrationsController

[Edit 7 août 2013] Maintenant, mette en place un outil qui permet de générer des contrôleurs: https://github.com/plataformatec/devise/wiki/Tool:-Generate-and-customize-controllers

Alors... de toute façon... j'ai réussi à obtenir ce "AnApprentice" je voulais juste écrire ce (pour une solution plus propre, voir big edit) :

#/my_project/app/helpers/devise_helper.rb
module DeviseHelper
   def devise_error_messages!
      return "" if resource.errors.empty?

      return resource.errors
   end
end

Et, à mon avis, la prochaine lignes assez bien travaillé:

<% devise_error_messages!.each do |key, value| %>
    <div class="flash <%= key %>"><%= key %> <%= value %></div>
<% end %>

Eh bien... vous pouvez accéder à des erreurs d'un attribut spécifique comme ceci:

    #Imagine you want only the first error to show up for the login attribute:
    <%= devise_error_messages![:login].first %> 

Et... Un petit truc pour avoir une seule erreur (le premier à l'avoir attrapé) montrant par attribut:

<% if resource.errors.any? %>
  <% saved_key = "" %>
  <% devise_error_messages!.each do |key, value| %>
    <% if key != saved_key %>
        <div class="flash <%= key %>"><%= key %> <%= value %></div>
    <% end %>
    <% saved_key = key %>
  <% end %>
<% end %>

Je sais que ça a été un moment depuis que cette question a été posté, mais je pense que ça aidera beaucoup de concevoir des utilisateurs :).

Gros Edit:

Comme j'aime à prolonger mon code, en le rendant plus clair et le partager avec d'autres, j'ai récemment voulu changer le devise_error_messages! méthode pour l'utiliser dans mon point de vue et qu'il affiche le truc que j'ai expliqué ci-dessus.

Donc, voici ma méthode:

 def devise_error_messages! 
    html = ""

    return html if resource.errors.empty?

    errors_number = 0 

    html << "<ul class=\"#{resource_name}_errors_list\">"

    saved_key = ""
    resource.errors.each do |key, value|
      if key != saved_key
        html << "<li class=\"#{key} error\"> This #{key} #{value} </li>"
        errors_number += 1
      end
      saved_key = key
    end

    unsolved_errors = pluralize(errors_number, "unsolved error")
    html = "<h2 class=\"#{resource_name}_errors_title\"> You have #{unsolved_errors} </h2>" + html
    html << "</ul>"

    return html.html_safe
 end

Pas grand-chose ici, j'ai réutilisé le code que j'ai écrit dans mon point de vue pour afficher une seule erreur pey attribut, parce que, souvent, le premier est la seule pertinente (par exemple, lorsque l'utilisateur oublie d'un champ obligatoire).

Je suis comptant ceux "unique" des erreurs et je suis en train de faire un H2 titre HTML à l'aide de pluraliser et de le mettre AVANT la liste des erreurs.

Alors maintenant, je peux utiliser le "devise_error_messages!" comme celui par défaut et le rendu est exactement ce que j'ai déjà été rendu avant.

Si vous souhaitez accéder à un message d'erreur spécifique à votre avis, je vais maintenant vous recommandons d'utiliser directement "des ressources.erreurs[:attribut].d'abord" ou quoi que ce soit.

Seya, Kulgar.

6voto

Scott Lowe Points 9412

Je suis l'aide de Concevoir dans Rails 3 et votre flash code est à peu près identique à ce que j'ai. Dans mon application, le code fonctionne comme prévu; c'est à dire Concevoir les messages d'erreur sont de sortie avec le reste de mes messages flash:

<% flash.each do |name, msg| %>
  <%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
<% end %>

Essayer ce code exact et voir si cela fait une différence - les différents ID de l'attribut peut aider.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X