Simple helper for conditional containers
July 6th, 2007
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.