ruby on rails - sintaxis - Rieles: una forma elegante de mostrar un mensaje cuando no hay elementos en la base de datos
sintaxis each ruby (9)
Como nota, también puede iterar sobre una matriz vacía si está buscando la eficacia de la expresión:
<% @messages.each do |message| %>
<%# code or partial to dispaly the message %>
<% end %>
<% if (@messages.blank?) %>
You have no messages.
<% end %>
Si bien esto no controla que los mensajes @ sean nulos, debería funcionar para la mayoría de las situaciones. La introducción de extensiones irregulares a lo que debería ser una vista de rutina probablemente esté complicando algo que de otra manera sería simple.
Lo que podría ser un mejor enfoque es definir un parcial y un ayudante para representar secciones "vacías" si estas son razonablemente complejas:
<% render_each(:message) do |message| %>
<%# code or partial to dispaly the message %>
<% end %>
# common/empty/_messages.erb
You have no messages.
Donde podrías definir esto como:
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
Me di cuenta de que estoy escribiendo muchos códigos similares a este:
<% unless @messages.blank? %>
<% @messages.each do |message| %>
<%# code or partial to display the message %>
<% end %>
<% else %>
You have no messages.
<% end %>
¿Hay alguna construcción en Ruby y / o Rails que me permita omitir esa primera condición? Entonces, ¿eso se ejecutará cuando iterator / loop no ingresará ni siquiera una vez? Por ejemplo:
<% @messages.each do |message| %>
<%# code or partial to display the message %>
<% and_if_it_was_blank %>
You have no messages.
<% end %>
Ese código se puede acortar a:
<%= @messages.empty? ? ''You have no messages.'' : @messages.collect { |msg| formatted_msg(msg) }.join(msg_delimiter) %>
Comentarios:
formatted_msg () - método auxiliar que agrega formato al mensaje
msg_delimiter - variable que contiene delimitador como "/ n" o " <br />
"
Por cierto, sugeriría usar vacío? método en lugar de en blanco? para verificar una matriz, porque a) su nombre es más conciso :) yb) en blanco? es un método de extensión de ActiveSupport que no funcionará fuera de Rails.
Me sorprende que mi respuesta favorita no esté aquí. Hay una respuesta que está cerca, pero no me gusta el texto desnudo y el uso de content_for es klunky. Prueba esto por tamaño:
<%= render(@user.recipes) || content_tag("p") do %>
This user hasn''t added any recipes yet!
<% end %>
Puede crear algunos ayudantes personalizados. El siguiente es solo un ejemplo.
# 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 %>
Puede dividir sus dos casos en diferentes plantillas: una si existen mensajes y otra si no existe ningún mensaje. En la acción del controlador (probablemente el MessagesController#index
), agregue como última instrucción:
render :action => ''index_empty'' if @messages.blank?
Si no hay mensajes, mostrará app/views/messages/index_empty.html.erb
. Si hay mensajes, se mostrará y mostrará app/views/messages/index.html.erb
como de costumbre.
Si necesita esto en más de una acción, puede refactorizarlo bien en un método auxiliar como el siguiente (no probado):
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
Con esto, solo necesitas poner render_action_or_empty(@var)
al final de cualquier acción del controlador y mostrará la plantilla ''acción'' o la plantilla ''action_empty'' si tu colección está vacía. También debería ser fácil hacer que esto funcione con parciales en lugar de plantillas de acción.
Si usa el parámetro :collection
para representar, por ejemplo, render :partial => ''message'', :collection => @messages
, la llamada a renderizar devolverá nil
si la colección está vacía. Esto puede ser incorporado en un || expresión, por ejemplo
<%= render(:partial => ''message'', :collection => @messages) || ''You have no messages'' %>
En caso de que no lo haya encontrado antes, render :collection
representa una colección usando el mismo parcial para cada elemento, haciendo que cada elemento de @messages
esté disponible a través del message
variable local a medida que construye la respuesta completa. También puede especificar que se represente un divisor entre cada elemento usando :spacer_template => "message_divider"
También podrías escribir algo como esto:
<% if @messages.each do |message| %>
<%# code or partial to display the message %>
<% end.empty? %>
You have no messages.
<% end %>
Tema antiguo pero realmente no me gustó ninguno de estos, por lo que jugué en Rails 3.2. Descubrí esta alternativa:
<% content_for :no_messages do %>
<p>
<strong>No Messages Found</strong>
</p>
<% end %>
<%= render @messages || content_for(:no_messages) %>
O si necesita un renderizado más detallado con una ruta parcial como lo hice yo:
<%= render(:partial => ''messages'',
:collection => @user.messages) || content_for(:no_messages) %>
De esta forma, puede personalizar la parte "sin mensajes" con la lógica de HTML / vista que desee y mantenerla agradable y fácil de leer.
Una forma es hacer algo como:
<%= render(:partial => @messages) || render(''no_messages'') %>
Editar:
Si recuerdo correctamente, esto fue posible gracias a este compromiso:
http://github.com/rails/rails/commit/a8ece12fe2ac7838407954453e0d31af6186a5db