Helper for quicly creating standard tables
1 2 def table(collection, headers, options = {}, &proc) 3 options.reverse_merge!({ 4 :placeholder => 'Nothing to display', 5 :caption => nil, 6 :summary => nil, 7 :footer => '' 8 }) 9 placeholder_unless collection.any?, options[:placeholder] do 10 summary = options[:summary] || "A list of #{collection.first.class.to_s.pluralize}" 11 output = "<table summary=\"#{summary}\">\n" 12 output << content_tag('caption', options[:caption]) if options[:caption] 13 output << "\t<caption>#{options[:caption]}</caption>\n" if options[:caption] 14 output << content_tag('thead', content_tag('tr', headers.collect { |h| "\n\t" + content_tag('th', h) })) 15 output << "<tfoot><tr>" + content_tag('th', options[:footer], :colspan => headers.size) + "</tr></tfoot>\n" if options[:footer] 16 output << "<tbody>\n" 17 concat(output, proc.binding) 18 collection.each do |row| 19 proc.call(row, cycle('odd', 'even')) 20 end 21 concat("</tbody>\n</table>\n", proc.binding) 22 end 23 end
Writing...
1 2 <% table(@posts, %w{ID title}) do |post, klass| -%> 3 <tr class="<%= klass %>"> 4 <td><%= post.id</td> 5 <td><%= post.title </td> 6 </tr> 7 <% end -%>
results in...
1 2 <table summary="A list of posts"> 3 <thead> 4 <tr> 5 <th>ID</th> 6 <th>Title</th> 7 </tr> 8 </thead> 9 <tfoot><tr><td colspan="2"></td></tr></tfoot> 10 <tbody> 11 <tr> 12 <td>1</td> 13 <td>My first post</td> 14 </tr> 15 </tbody> 16 </table>
Or, when the collection is an empty array (collection.any? returns false), a placeholder message is displayed:
1 2 <p class="placeholder">Nothing to display</p>
So you pass in your collection and an array of strings as your table headers as the first two arguments, and the third is a hash of options you can use to set the contents of the table's summary-attribute, the caption and footer-elements and the placeholder.
The summary attribute defaults to "A list of [objects]", where 'objects' is derived from the class name of the collection.
The function finally takes a block for every element in the collection, yeilding it the element and either 'odd' or 'even' so you can use CSS-classes to apply a zebra stripes effect.