J’ai réalisé que j’écrivais beaucoup de code similaire à celui-ci:
You have no messages.
Y a-t-il une construction dans Ruby et / ou Rails qui me permettrait de sauter cette première condition? Donc, ce serait exécuté quand l’iterator / boucle n’entre pas même une fois? Par exemple:
You have no messages.
Si vous utilisez le paramètre :collection
pour effectuer un rendu, par exemple render :partial => 'message', :collection => @messages
alors l’appel à render retournera nil
si la collection est vide. Cela peut ensuite être incorporé dans un || expression par exemple
<%= render(:partial => 'message', :collection => @messages) || 'You have no messages' %>
Au cas où vous ne l’auriez jamais rencontré auparavant, render :collection
rend une collection utilisant le même partiel pour chaque élément, rendant chaque élément de @messages
disponible via le message
variable locale lorsqu’il construit la réponse complète. Vous pouvez également spécifier un diviseur à rendre entre chaque élément en utilisant :spacer_template => "message_divider"
Vous pourriez aussi écrire quelque chose comme ceci:
<% if @messages.each do |message| %> <%# code or partial to display the message %> <% end.empty? %> You have no messages. <% end %>
Une façon de faire est de faire quelque chose comme:
<%= render(:partial => @messages) || render('no_messages') %>
Modifier:
Si je me souviens bien, cela a été rendu possible par cet engagement:
http://github.com/rails/rails/commit/a8ece12fe2ac7838407954453e0d31af6186a5db
Je suis surpris que ma réponse préférée ne soit pas là. Il y a une réponse proche, mais je n’aime pas le texte nu et l’utilisation de content_for est klunky. Essayez celui-ci pour la taille:
<%= render(@user.recipes) || content_tag("p") do %> This user hasn't added any recipes yet! <% end %>
Vous pouvez créer un assistant personnalisé. Le suivant est juste 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 %>
En tant que note, vous pouvez aussi simplement parcourir un tableau vide si vous recherchez l’efficacité de l’expression:
<% @messages.each do |message| %> <%# code or partial to dispaly the message %> <% end %> <% if (@messages.blank?) %> You have no messages. <% end %>
Bien que cela ne gère pas @messages comme étant nul, cela devrait fonctionner dans la plupart des cas. Introduire des extensions irrégulières à ce qui devrait être une vue de routine complique probablement une chose par ailleurs simple.
Ce qui pourrait être une meilleure approche est de définir un partiel et un assistant pour rendre les sections “vides” si celles-ci sont raisonnablement complexes:
<% render_each(:message) do |message| %> <%# code or partial to dispaly the message %> <% end %> # common/empty/_messages.erb You have no messages.
Où vous pouvez définir cela comme:
def render_each(item, &block) plural = "#{item.to_s.pluralize}" items = instance_variable_get("@#{plural}") if (items.blank?) render(:partial => "common/empty/#{plural}") else items.each(&block) end end
Ancien sujet mais je n’aimais pas vraiment ces jeux, alors je me suis amusé avec Rails 3.2. J’ai trouvé cette alternative:
<% content_for :no_messages do %> No Messages Found
<% end %> <%= render @messages || content_for(:no_messages) %>
Ou si vous avez besoin d’un rendu plus verbeux avec un chemin partiel comme je l’ai fait:
<%= render(:partial => 'messages', :collection => @user.messages) || content_for(:no_messages) %>
De cette façon, vous pouvez styler la partie “no messages” avec la logique HTML / de vue souhaitée et la garder agréable à lire.
Ce code peut être raccourci à:
<%= @messages.empty? ? 'You have no messages.' : @messages.collect { |msg| formatted_msg(msg) }.join(msg_delimiter) %>
Commentaires:
formatted_msg () – méthode d’assistance qui ajoute une mise en forme au message
msg_delimiter – variable contenant un délimiteur comme “\ n” ou ”
”
BTW je suggère d’utiliser vide? méthode au lieu de blanc? pour vérifier un tableau, car a) son nom est plus concis 🙂 et b) vide? est une méthode d’extension ActiveSupport qui ne fonctionnera pas en dehors de Rails.
Vous pouvez diviser vos deux cas en différents modèles: un si des messages existent et un si aucun message n’existe. Dans l’action du contrôleur ( MessagesController#index
probablement), ajoutez comme dernière instruction:
render :action => 'index_empty' if @messages.blank?
S’il n’y a pas de message, il affichera app/views/messages/index_empty.html.erb
. S’il y a des messages, il tombera et affichera app/views/messages/index.html.erb
comme d’habitude.
Si vous en avez besoin dans plus d’une action, vous pouvez facilement le transformer en une méthode d’assistance comme celle-ci (non testée):
def render_action_or_empty (collection, options = {}) template = params[:template] || "#{params[:controller]}/#{params[:action]}" template << '_empty' if collection.blank? render options.reverse_merge { :template => template } end
Avec cela, il vous suffit de mettre render_action_or_empty(@var)
à la fin de toute action du contrôleur et cela affichera le modèle «action» ou le modèle «action_empty» si votre collection est vide. Il devrait également être facile de faire ce travail avec des partiels au lieu de modèles d’action.