J'ai réalisé que j'écrivais 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 %>
Y a-t-il une construction dans Ruby et/ou Rails qui me permettrait de sauter cette première condition? Donc, cela serait exécuté lorsque l'itérateur/boucle n'entre pas même une fois? Par exemple:
<% @messages.each do |message| %>
<%# code or partial to display the message %>
<% and_if_it_was_blank %>
You have no messages.
<% end %>
Si vous utilisez le :collection
paramètre à rendre par exemple render :partial => 'message', :collection => @messages
alors l'appel au rendu 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 pas encore rencontré, rendez :collection
rend une collection en utilisant le même partiel pour chaque élément, ce qui rend chaque élément de @messages
disponible via la variable locale message
lors de l'élaboration de la réponse complète. Vous pouvez également spécifier un séparateur à rendre entre chaque élément en utilisant :spacer_template => "message_divider"
Vous pouvez également écrire quelque chose comme ceci:
<% if @messages.each do |message| %>
<%# code or partial to display the message %>
<% end.empty? %>
You have no messages.
<% end %>
Je suis surpris que ma réponse préférée ne soit pas ici. Il y a une réponse qui est proche, mais je n'aime pas le texte nu et utiliser 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 %>
Une façon est de faire quelque chose comme:
<%= render(:partial => @messages) || render('no_messages') %>
Éditer:
Si je me souviens bien, cela a été rendu possible par ce commit:
http://github.com/Rails/rails/commit/a8ece12fe2ac7838407954453e0d31af6186a5db
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 %>
En guise de 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 les @messages étant nuls, cela devrait fonctionner dans la plupart des situations. L'introduction d'extensions irrégulières à ce qui devrait être une vue de routine complique probablement une chose par ailleurs simple.
La meilleure approche pourrait être de définir une section partielle et une aide 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 pourriez 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
Vieux sujet mais je n'aimais vraiment aucun de ceux-ci, alors jouer sur Rails 3.2 J'ai compris cette alternative:
<% content_for :no_messages do %>
<p>
<strong>No Messages Found</strong>
</p>
<% end %>
<%= render @messages || content_for(:no_messages) %>
Ou si vous avez besoin d'un rendu plus détaillé 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 styliser la partie "pas de messages" avec la logique HTML/vue que vous voulez et la garder facile à lire.
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 la refactoriser 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 il affichera soit le modèle 'action' ou le modèle 'action_empty' si votre collection est vide. Il devrait également être facile de faire fonctionner cela avec des partiels au lieu de modèles d'action.
La solution ci-dessous fonctionne pour moi car je veux tr
et td
avec la propriété colspan
:
<%= render(@audit_logs) || content_tag(:tr, content_tag(:td, 'No records',colspan: "11"))%>
Ce code peut être abrégé en:
<%= @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 "<br />
"
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.