Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I manage if-then explosion in view files?

I apologize if this doesn't follow good question guidelines, but I hope it's well in class with How to Manage CSS Explosion and receives a similarly helpful response.

I'm familiar with some basic view prolixity mitigation strategies such as the following:

  • Use helpers where appropriate
  • Don't repeat yourself
  • Use partials and layouts

Feel free to suggest something if I'm missing some big idea in the above list.

Nevertheless, I still end up with having several dimensions/degrees of freedom in my view, causing a lot of if-then statements or at least ternary blocks. For instance, in something I'm currently messing with, I'm working on a header bar for a program where the view is called when three "big" variables:

  • Whether the user is admin
  • Whether the user is logged in
  • Whether the page being viewed belongs to the user or someone else

It ends up looking like this mess:

<% content_for :subheader do %>
  <div class="row">
    <% if @user %>
      <% if @user == current_user %>
        <%= link_to 'My programs', user_programs_path(current_user), :class => 'active' %>
      <% else %>
        <%= link_to "#{@user.username}'s programs", user_programs_path(@user), :class => 'active' %>
      <% end %>
      <%= link_to 'Browse all programs', programs_path %>
    <% else %>
      <% if current_user %>
        <%= link_to 'My programs', user_programs_path(current_user) %>
      <% end %>
      <%= link_to 'Browse all programs', programs_path, :class => 'active' %>
    <% end %>
    <%= link_to 'New Program', new_program_path, :class => 'admin' if current_user.admin? %>
  </div>
  <% if @regions %>
    <div class="row second">
      <%= link_to 'Regional program search', request.fullpath, :class => 'active' %>
    </div>
  <% end %>
<% end %>

Ugly. Readable and easily accessible, but ugly. Some suggestions?

Between experience and new technologies like LESS, I've become pretty good at slimming down my CSS files, but I'm still running into explosion issues with my MVC views.

like image 288
Steven Avatar asked Feb 16 '11 23:02

Steven


1 Answers

I would use helpers and model definitions to dry up your code:

class User
  def possesive
    self == current_user ? 'My' : "#{username}'s"
  end
end

module ...Helper
  def user_program_link user
    if user
      link_to "#{user.possesive} programs", user_programs_path(user), :class => 'active'
    elsif current_user
      link_to 'My programs', user_programs_path(current_user)
    end
  end
end

You can then simplify all the if statements for the user_program_path calls to this:

<%= user_program_link @user %>

Which would reduce your view code to:

<% content_for :subheader do %>
  <div class="row">
    <%= user_program_link @user %>
    <% if @user %>
      <%= link_to 'Browse all programs', programs_path %>
    <% else %>
      <%= link_to 'Browse all programs', programs_path, :class => 'active' %>
    <% end %>
    <%= link_to 'New Program', new_program_path, :class => 'admin' if current_user.admin? %>
  </div>
  <% if @regions %>
    <div class="row second">
      <%= link_to 'Regional program search', request.fullpath, :class => 'active' %>
    </div>
  <% end %>
<% end %>

Continue this process to DRY up the rest of your code as well.

like image 159
Pan Thomakos Avatar answered Sep 30 '22 09:09

Pan Thomakos