Rails:在数据库中没有元素时显示消息的优雅方式

Jak*_*zok 66 ruby iterator loops ruby-on-rails

我意识到我正在写很多类似于这个的代码:

<% unless @messages.blank? %>
  <% @messages.each do |message|  %>
    <%# code or partial to display the message %>
  <% end %>
<% else %>
  You have no messages.
<% end %>
Run Code Online (Sandbox Code Playgroud)

Ruby和/或Rails中是否有任何构造可以让我跳过第一个条件?所以当迭代器/循环不会进入一次时会执行?例如:

<% @messages.each do |message| %>
  <%# code or partial to display the message %>
<% and_if_it_was_blank %>
  You have no messages.
<% end %>
Run Code Online (Sandbox Code Playgroud)

小智 159

你也可以写这样的东西:

<% if @messages.each do |message| %>
  <%# code or partial to display the message %>
<% end.empty? %>
  You have no messages.
<% end %>
Run Code Online (Sandbox Code Playgroud)

  • 你怎么用haml/slim做这样的事情? (7认同)
  • 我喜欢这个答案.我自己使用了这个,超级干净,非常容易理解. (6认同)

mik*_*kej 61

如果使用:collection参数渲染eg,render :partial => 'message', :collection => @messages那么nil如果集合为空,则将返回对render的调用.然后可以将其合并到||中 表达例如

<%= render(:partial => 'message', :collection => @messages) || 'You have no messages' %>
Run Code Online (Sandbox Code Playgroud)

如果之前没有遇到过它,渲染:collection会使用相同的部分为每个元素渲染一个集合,使每个元素在构建完整响应时@messages通过局部变量可用message.您还可以使用指定要在每个元素之间呈现的分隔符:spacer_template => "message_divider"

  • 我认为费尔南多·艾伦的解决方案应该作为可能的替代方案添加到这个答案中,因为人们可能会跳过它,因为它不是"最佳答案". (3认同)

Dav*_*ock 17

我很惊讶我最喜欢的答案不在这里.有一个答案很接近,但我不喜欢裸文,使用content_for是笨拙的.试试这个尺寸:

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

  • **重要:**不要忘记`render`的括号,否则`||`将不适用于`render`的结果,而是适用于集合本身.我自己也写了同样的东西,但由于这个原因它起作用(起初). (7认同)

jon*_*nii 16

一种方法是做一些事情:

<%= render(:partial => @messages) || render('no_messages') %>
Run Code Online (Sandbox Code Playgroud)

编辑:

如果我没记错的话,这可以通过这个提交来实现:

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


Sim*_*tti 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 %>
Run Code Online (Sandbox Code Playgroud)