I often come into situation where I want to add a some content wrapped inside a container only if some condition is true, usually some item should be non-empty. For example, consider the following Rails view:

1
2
3
4
5
6
7
8
9
<h2>My beverages on the fridge</h2>

<% if !@cans.empty %>
  <ul>
    <% @cans.each do |beverage| %>
      <li id="#can_{beverage.id}">beverage.name</li>
    <% end %>
  </ul>
<% end %>

But it’s so ugly my eyes hurt. Because Ruby is so easy language with which to create natural-sounding expressions, I whipped up the following method and stashed it to application_helper.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 ##
 # create a container tag around each subelement in object unless
 # object fails +:unless+ condition (which by default is
 # object.empty). This is handy for avoiding creation of empty
 # container elements:

  def contain_each_of(object, opts)
    opts[:unless] = object.empty? if opts[:unless].nil?

    opts.reverse_merge( { :in => :div } )
    container = opts[:in]
    raise ArgumentError("method requires block") unless block_given?
    if object && !opts[:unless]
      content_tag(container) do
        object.each { |item| yield item }
      end
    else
      content_tag(container, opts[:default]) unless opts[:default]
    end
  end

Usage is now not only easier but more pleasant to the eyes as well:

1
2
3
4
5
<h2>My beverages on the fridge</h2>

 <% contain_each_of(@cans, :in => :ul) do |can| %>
     <li id="#can_{beverage.id}">beverage.name</li>
  <% end %>

And ‘lo mama, with custom (though contrived) condition:

1
2
3
4
5
<h2>My cool beverages on the fridge</h2>

 <% contain_each_of(@cans, :in => :ul, :unless => @cans.any? {|b| b.temperature == :not_so_cold} ) do |can| %>
     <li id="#can_{beverage.id}">beverage.name</li>
  <% end %>

Sorry, comments are closed for this article.