我意识到我正在编写许多与此类似的代码:
<% unless @messages.blank? %>
<% @messages.each do |message| %>
<%# code or partial to display the message %>
<% end %>
<% else %>
You have no messages.
<% end %>
Ruby和/或Rails中是否有任何构造可以让我跳过它 第一个条件?所以当迭代器/循环不会进入一次时会执行?对于 例如:
<% @messages.each do |message| %>
<%# code or partial to display the message %>
<% and_if_it_was_blank %>
You have no messages.
<% end %>
答案 0 :(得分:159)
你也可以这样写:
<% if @messages.each do |message| %>
<%# code or partial to display the message %>
<% end.empty? %>
You have no messages.
<% end %>
答案 1 :(得分:60)
如果您使用:collection
参数进行渲染,例如render :partial => 'message', :collection => @messages
如果集合为空,则对render的调用将返回nil
。然后可以将其合并到||中表达,例如。
<%= render(:partial => 'message', :collection => @messages) || 'You have no messages' %>
如果您之前没有遇到过它,渲染:collection
会为每个元素使用相同的部分呈现集合,通过局部变量@messages
使message
的每个元素都可用因为它建立了完整的响应。您还可以使用:spacer_template => "message_divider"
答案 2 :(得分:16)
一种方法是做一些事情:
<%= render(:partial => @messages) || render('no_messages') %>
编辑:
如果我没记错的话,这可以通过这个提交来实现:
http://github.com/rails/rails/commit/a8ece12fe2ac7838407954453e0d31af6186a5db
答案 3 :(得分:16)
我很惊讶我最喜欢的答案不在这里。有一个答案很接近,但我不喜欢裸文,使用content_for是笨拙的。试试这个尺寸:
<%= render(@user.recipes) || content_tag("p") do %>
This user hasn't added any recipes yet!
<% end %>
答案 4 :(得分:6)
您可以创建一些自定义帮助程序。以下是一个例子。
# 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 %>
答案 5 :(得分:3)
作为一个注释,如果你正在寻找表达效率,你也可以迭代一个空数组:
<% @messages.each do |message| %>
<%# code or partial to dispaly the message %>
<% end %>
<% if (@messages.blank?) %>
You have no messages.
<% end %>
虽然这不能处理@messages为零,但它应该适用于大多数情况。引入应该是例行视图的不规则扩展可能会使一个简单的事情复杂化。
可能更好的方法是定义部分和辅助以呈现“空”部分,如果它们相当复杂:
<% render_each(:message) do |message| %>
<%# code or partial to dispaly the message %>
<% end %>
# common/empty/_messages.erb
You have no messages.
您可以将其定义为:
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
答案 6 :(得分:1)
老话题,但我真的不喜欢其中的任何一个,所以在Rails 3.2上玩这个我想出了这个替代方案:
<% content_for :no_messages do %>
<p>
<strong>No Messages Found</strong>
</p>
<% end %>
<%= render @messages || content_for(:no_messages) %>
或者,如果您需要像我一样使用部分路径进行更详细的渲染:
<%= render(:partial => 'messages',
:collection => @user.messages) || content_for(:no_messages) %>
通过这种方式,您可以使用您想要的任何HTML /视图逻辑设置“无消息”部分的样式,并使其易于阅读。
答案 7 :(得分:0)
该代码可以缩短为:
<%= @messages.empty? ? 'You have no messages.' : @messages.collect { |msg| formatted_msg(msg) }.join(msg_delimiter) %>
评论:
formatted_msg() - 为消息添加格式的辅助方法
msg_delimiter - 包含分隔符的变量,如“\ n”或“<br />
”
答案 8 :(得分:0)
您可以将两个案例分成不同的模板:一个是邮件存在,另一个是不存在邮件。在控制器操作中(可能是MessagesController#index
),添加为最后一个语句:
render :action => 'index_empty' if @messages.blank?
如果没有消息,则会显示app/views/messages/index_empty.html.erb
。如果有消息,它将会照常显示app/views/messages/index.html.erb
。
如果你需要的不仅仅是一个动作,你可以很好地将它重构为一个辅助方法,如下所示(未经测试):
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
有了这个,您只需要在任何控制器操作结束时放置render_action_or_empty(@var)
,如果您的集合为空,它将显示'action'模板或'action_empty'模板。使用partials而不是动作模板也可以很容易地使用它。
答案 9 :(得分:0)
以下解决方案对我有用,因为我想要tr
和td
具有colspan
属性:
<%= render(@audit_logs) || content_tag(:tr, content_tag(:td, 'No records',colspan: "11"))%>