16

I need an advice on best practices for DRYing view code. I have three classes (NewsItem, RssItem and BlogItem) in my app, that use separate views, but have similar parts in them. One of the parts is such:

<% if current_user %>
<footer>
  <%= marks_bar(@item) %>
  <%= favorite_button(@item, "blog_item") || delete_from_favorite_button(@item, "blog_item") %>
  <%= share_button(@item) %>
  <% if current_user.is_mine?(@item) %>
    <div><%= link_to "Edit", edit_user_blog_item_path(current_user, @item) %></div>
  <% end %>
</footer>
<% end %>

It's almost equal for all three classes, so I decided to take it out to some separate place. And here I am confused: should I use a partial or helper method for it? I know that helpers are used mostly for separating ruby code from HTML, but in this case the helper will look like:

def toolbar_for(item, type_str, edit_path)
  if current_user
    content_tag(:footer) do |b|
      marks_bar(item).to_s <<
      (delete_from_favorite_button(item, type_str) || favorite_button(@item, type_str)).to_s <<
      share_button(@item).to_s <<
      (content_tag(:div) { link_to("Edit", edit_path)} if current_user.is_mine?(@item)).to_s
    end
  end
end

So, there is almost no HTML code here.

Could you please give me advice, what method is better in your opinion and why? Also, are there some performance issues in these methods (for example multiple String concatenation or frequent partial loading might be costly)? (This app is rather high-loaded)

Chris
  • 332
  • 3
  • 8
sandrew
  • 3,109
  • 5
  • 19
  • 29

2 Answers2

17

I would say this is a great example of a partial.

I reserve helpers for generating arbitrary dynamic content. This is kind of a loose description so how about an example: I would make a helper that splits an array of ActiveRecord objects and displays them into N columns. In this case the passed object's structure is being leveraged in some way in order to generate the content, but the content itself is unimportant. If you think about it, form_for also fits this description.

Conversely partials are great for 'static' content, that needs to be reused on multiple pages. For instance you would create a partial to render a single item. The partial determines a particular items 'static' representation.

Your example fits much better into the second bin, in my opinion. Since the @item isn't being manipulated to generate the content, in fact it is hardly being used. It seems this helper is mostly glue code for other appropriately created helpers (share_button and marks_bar). The perfect use case for a partial!

diedthreetimes
  • 4,086
  • 26
  • 38
5

I'd use a view partial for this. Good rule of thumb: if HTML is the output, use a partial. Helpers are not the junk drawer of your Rails app—they should really be used to output data, not presentation. Though I usually recommend people eschew helpers in general, in favor of presenters, which are vastly underutilized in the Rails world.

Keith Gaddis
  • 4,113
  • 23
  • 20
  • 7
    well, actually I don't think, that "if HTML is the output, use a partial" is the only truth. the fact is that form_for, link_to and so on - are helpers too. – sandrew Jul 27 '11 at 18:31
  • No, its certainly not the only opinion on the matter. And certainly that pattern is used successfully in places, including form builders. But if you're asking the question about which is more appropriate instead of having your own instinct about it, I humbly submit that partials are a simpler and more straightforward approach that will be more maintainable in the long run. – Keith Gaddis Jul 27 '11 at 19:34
  • I appreciate you for your opinion, but I think it is rather subjective. I think maintainability comparison of helper methods and partials is more a matter of a taste of each developer, untill I'll see more objective arguments. – sandrew Jul 28 '11 at 05:01