68 votes

Rails : Une manière élégante d'afficher un message lorsqu'il n'y a pas d'éléments dans la base de données

Je me suis rendu compte que j'écris beaucoup de code similaire à celui-ci :

<% unless @messages.blank? %>
  <% @messages.each do |message|  %>
    <%# code or partial to display the message %>
  <% end %>
<% else %>
  You have no messages.
<% end %>

Existe-t-il une construction en Ruby et/ou Rails qui me permettrait d'éviter ce première condition ? Pour qu'elle soit exécutée lorsque l'itérateur/la boucle n'entre pas une seule fois ? Pour exemple :

<% @messages.each do |message| %>
  <%# code or partial to display the message %>
<% and_if_it_was_blank %>
  You have no messages.
<% end %>

167voto

Fernando Allen Points 746

Vous pourriez aussi écrire quelque chose comme ça :

<% if @messages.each do |message| %>
  <%# code or partial to display the message %>
<% end.empty? %>
  You have no messages.
<% end %>

6 votes

J'adore cette réponse. J'ai utilisé celle-ci parmi toutes les autres, super propre et très compréhensible.

1 votes

Superbe réponse, très succincte.

7 votes

Comment faire quelque chose comme ça en haml/slim ?

64voto

mikej Points 30224

Si vous utilisez le :collection pour effectuer le rendu, par exemple render :partial => 'message', :collection => @messages alors l'appel à render retournera nil si la collection est vide. Ceci peut alors être incorporé dans une expression ||, par exemple

<%= render(:partial => 'message', :collection => @messages) || 'You have no messages' %>

Au cas où vous ne l'auriez pas encore vu, le rendu :collection rend une collection en utilisant le même partiel pour chaque élément, rendant chaque élément de @messages disponible par le biais de la variable locale message pendant qu'il construit la réponse complète. Vous pouvez également spécifier un séparateur à rendre entre chaque élément à l'aide de la fonction :spacer_template => "message_divider"

1 votes

Great... how about a before collection and after collection? say you want to have <ul> and </ul> or <tr></tr> tag pairs before and after the partial rendering but only if the @messages ar enot empty. examples- > <p><ul><li>message1</li><message2></ul><p> is @messages!=nil OR <p><ul>no messages!<p>

3 votes

Je pense que la solution de Fernando Allen devrait être ajoutée à cette réponse comme alternative possible, car les gens pourraient la sauter parce qu'elle n'est pas la "meilleure réponse".

1 votes

Juste une petite note qui peut être utile. pour que cette syntaxe fonctionne, vous devez utiliser des parenthèses autour de l'élément partial Sans eux, le rendu du partiel est correct, mais le message conditionnel ne l'est pas.

18voto

David Bock Points 318

Je suis surpris que ma réponse préférée ne soit pas ici. Il y a une réponse qui s'en rapproche, mais je n'aime pas le texte brut et l'utilisation de content_for est peu pratique. Essayez celle-ci pour la taille :

  <%= render(@user.recipes) || content_tag("p") do %>
    This user hasn't added any recipes yet!
  <% end %>

1 votes

C'est ma réponse préférée jusqu'à présent.

7 votes

Important : n'oubliez pas les parenthèses pour render sinon le || ne s'appliquera pas au résultat de render mais à la collection elle-même. Je viens d'écrire la même chose moi-même, mais cela n'a pas fonctionné (au début) à cause de cela.

1 votes

C'est la solution élégante que je recherchais :)

17voto

jonnii Points 17046

Une façon de faire est de faire quelque chose comme :

<%= render(:partial => @messages) || render('no_messages') %>

Edit :

Si je me souviens bien, cela a été rendu possible par ce commit :

http://github.com/rails/rails/commit/a8ece12fe2ac7838407954453e0d31af6186a5db

6voto

Simone Carletti Points 77653

Vous pouvez créer une aide personnalisée. Le suivant n'est qu'un exemple.

# application_helper.html.erb
def unless_empty(collection, message = "You have no messages", &block)
  if collection.empty?
    concat(message)
  else
    concat(capture(&block))
  end
end

# view.html.erb
<% unless_empty @messages do %>
  <%# code or partial to dispaly the message %>
<% end %>

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