Inspired by the projects table_builder and formtastic, I realized how often I created tables for my active record collections. This is my attempt to simplify this (the default scaffold):
<table> <tr> <th>Title</th> <th>Body</th> <th>Author Id</th> </tr> <% for post in @posts %> <tr> <td><%=h post.title %></td> <td><%=h post.body %></td> <td><%=h post.author_id %></td> <td><%= link_to "Show", post %></td> <td><%= link_to "Edit", edit_post_path(post) %></td> <td><%= link_to "Destroy", post, :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table>
into this:
<% table_for(@posts) do |t| %> <%= t.data :actions => :all %> <% end %>
and still output the same effective results, but with all the semantic goodness that tabular data should have, i.e. a thead
and tbody
element.
In your Rails project, as a gem:
config.gem "tabletastic", :source => "http://gemcutter.org"
Or, for if you’re behind the times, as a plugin:
script/plugin install git://github.com/jgdavey/tabletastic.git
By default, you can just use the table_for method to build up your table. Assuming you have a Post model with title and body, that belongs to an Author model with a name, you can just use the helper. It will try to detect all content fields and belongs to associations.
In your view, simply calling:
<% table_for(@posts) do |t| %> <%= t.data %> <% end %>
will produce html like this:
<table id="posts"> <thead> <tr> <th>Title</th> <th>Body</th> <th>Author</th> </tr> </thead> <tbody> <tr class="post odd" id="post_1"> <td>Something</td> <td>Lorem ipsum dolor sit amet consequat. Duis aute irure dolor.</td> <td>Jim Beam</td> </tr> <tr class="post even" id="post_2"> <td>Second Post</td> <td>This is the second post</td> <td>Jack Daniels</td> </tr> <tr class="post odd" id="post_3"> <td>Something else</td> <td>Blah!</td> <td></td> </tr> </tbody> </table>
To limit the fields, change the order, or to include fields that are excluded by default (such as created_at), You can list methods to call on each resource:
<% table_for(@posts) do |t| %> <%= t.data :author, :title, :created_at %> <% end %>
will produce html like:
<table id="posts"> <thead> <tr> <th>Author</th> <th>Title</th> <th>Created at</th> </tr> </thead> <tbody> <tr id="post_1" class="post odd"> <td>Jim Beam</td> <td>Something</td> <td>2009-11-15 02:42:48 UTC</td> </tr> <tr id="post_2" class="post even"> <td>Jack Daniels</td> <td>Second Post</td> <td>2009-11-16 00:11:00 UTC</td> </tr> <tr id="post_3" class="post odd"> <td></td> <td>Something else</td> <td>2009-11-16 00:11:30 UTC</td> </tr> </tbody> </table>
For even greater flexibility, you can pass data
a block:
<% table_for(@posts) do |t| %> <% t.data :actions => :all do %> <%= t.cell(:title, :cell_html => {:class => "titlestring"}) %> <%= t.cell(:body, :heading => "Content") {|p| truncate(p.body, 30)} %> <%= t.cell(:author) {|p| p.author && link_to(p.author.name, p.author) } %> <% end -%> <% end %>
will product html like:
<table id="posts"> <thead> <tr> <th>Title</th> <th>Content</th> <th>Author</th> <th></th> <th></th> <th></th> </tr> </thead> <tbody> <tr class="post odd" id="post_1"> <td class="titlestring">Something</td> <td>Lorem ipsum dolor sit amet,...</td> <td> <a href="/authors/1">Jim Bean</a> </td> <td class="actions show_link"> <a href="/posts/1">Show</a> </td> <td class="actions edit_link"> <a href="/posts/1/edit">Edit</a> </td> <td class="actions destroy_link"> <a href="/posts/1/edit">Destroy</a> <!-- inline javascript omitted --> </td> </tr> <tr class="post even" id="post_2"> <td class="titlestring">Second Post</td> <td>This is the second post</td> <td> <a href="/authors/2">Jack Daniels</a> </td> <td class="actions show_link"> <a href="/posts/2">Show</a> </td> <td class="actions edit_link"> <a href="/posts/2/edit">Edit</a> </td> <td class="actions destroy_link"> <a href="/posts/2/edit">Destroy</a> <!-- inline javascript omitted --> </td> </tr> <tr class="post odd" id="post_3"> <td class="titlestring">Something else</td> <td>Blah!</td> <td></td> <td class="actions show_link"> <a href="/posts/3">Show</a> </td> <td class="actions edit_link"> <a href="/posts/3/edit">Edit</a> </td> <td class="actions destroy_link"> <a href="/posts/3/edit">Destroy</a> <!-- inline javascript omitted --> </td> </tr> </tbody> </table>
If it still isn’t flexible enough for your needs, it might be time to return to static html/erb.
-
Fork the project.
-
Make your feature addition or bug fix.
-
Add tests for it. This is important so I don’t break it in a future version unintentionally.
-
Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
-
Send me a pull request. Bonus points for topic branches.
Copyright © 2009 Joshua Davey. See LICENSE for details.