Topic: Help DRYing out a partial and fixing some view logic

I have a partial that lists all the clients with dividers for the first letter of the last name so it would look like:
A________________
    Alexander, Tom
    Arrington, Luke
B_________________
    Bullock, Bob
C_________________
    Copeland, Justin

Now, in the client list view I sort the clients by different criteria. What I would like to do is reuse this logic, the only difference being the list divider. So instead of using client.last_name.first as I have now I would like to render this same partial but with the divider set as client.court.abbreviation.

I can already get at the .court.abbreviation from my client object, I just dont know how to reuse this piece of code without creating a new partial for each type of sort I use.

Here is my _client_list.rhtml partial.

<div id="client-list">
    <table class="list" cellpadding="0" cellspacing="0">
        <% last_client = @clients[0] %>
        <% for client in @clients %>
            <% if (client.last_name.first != last_client.last_name.first) || (last_client == client) %>
                <tr>
                    <td id="<%= client.last_name.first %>" class="list-divider" colspan="5"><%= client.last_name.first %> ______________________________________</td>
                </tr>
            <% end %>
          <tr>
                <td width="30px"></td>
                <td><%= link_to_remote client.last_name_first_name, :url => {:action => 'display_client_info', :id => client} %></td>
            <td><%= client.matters.count %></td>
            <td><%= number_to_phone(client.phone, :area_code => true, :delimiter => "-") %></td>
          </tr>
            <% last_client = client %>
        <% end %>
    </table>
</div>

my messy controller code:
class ClientsController < ApplicationController
...
def active
    #used to list all active clients
    case params[:sort]
      when 'by_court'
        @clients = Client.find(:all,
                               :include => {:matters => :court},
                               :conditions => ['matters.open = ?', true],
                               :order => 'courts.abbreviation, last_name')
      when 'by_setting'
        @clients = Client.find(:all,
                               :include => {:matters => [:court, {:court_dates => :court_date_type}]},
                               :conditions => ['matters.open = ?', true],
                               :order => 'court_date_types.abbreviation, last_name')
      else
        # default to sort by name
        @clients = Client.find(:all,
                               :include => :matters,
                               :conditions => ['open = ?', true],
                               :order => "last_name")
    end
   
    render :action => 'list'
  end

  def today
    #similar to active only different conditions are used to return only clients with meetings today
    ...
    render :action => 'list'
  end

  def all
    #similar to active and today. lists all clients, even those that are no longer active.
    ...
    render :action => 'list'
  end

  def list
  end
...
end


list.rhtml view: Things brings up another question: how do i determine which controller method rendered this view, since I call render :action => 'list' from a few different methods in my Clients controller I want to automatically adjust the :action in my 'Sort by' links to use whatever method rendered this view.:

<% @page_title = "Clients" %>
<div id="client-list-pane">
    <%= link_to "Active Clients", :action => 'active' %> | <%= link_to "Today's Clients", :action => 'today' %> |
    <%= link_to "All Clients", :action => 'all' %><br/>
    Sort: <%= link_to "By Name", :action => 'active', :sort => 'by_name' %> | <%= link_to "By Court", :action => 'active', :sort => 'by_court' %> | <%= link_to "By Setting", :action => 'active', :sort => 'by_setting' %><br/><br/>
    <%= render :partial => "client_list" %>
    <%= link_to "+ Add New Client ...", :action => 'new' %><br /><br />
</div>
<div id="clientDetailPane">
    <h3>Select a Client to View Contact Information and Case Details.</h3>
</div>
<div id="clientMatterDetailPane">
</div>

I realize this is a mess and needs to be DRYed / refactored somehow. Looking forward to any suggestions. Thanks a ton guys. This board has been the best way to get answers to my questions so far, and I really do appreciate that.

Re: Help DRYing out a partial and fixing some view logic

There's this little method called group_by which I think you will really like. It allows you to group models by the first character of the name, court abbreviation - anything. Use it like this:

@client_groups = @clients.group_by { |c| c.last_name.first }

# or

@client_groups = @clients.group_by { |c| c.court.abbreviation }


This will make a hash where the key is the abbreviation/character, and the value is the array of clients. You can use it in your view like this:

<div id="client-list">
  <table class="list" cellpadding="0" cellspacing="0">
    <% @client_groups.each do |group, clients| %>
      <tr>
        <td id="<%= group %>" class="list-divider" colspan="5"><%= group %> ______________________________________</td>
      </tr>
      <% for client in clients %>
        <tr>
          <td width="30px"></td>
          <td><%= link_to_remote client.last_name_first_name, :url => {:action => 'display_client_info', :id => client} %></td>
          <td><%= client.matters.count %></td>
          <td><%= number_to_phone(client.phone, :area_code => true, :delimiter => "-") %></td>
        </tr>
      <% end %>
    <% end %>
  </table>
</div>

jmcopeland wrote:

list.rhtml view: Things brings up another question: how do i determine which controller method rendered this view, since I call render :action => 'list' from a few different methods in my Clients controller I want to automatically adjust the :action in my 'Sort by' links to use whatever method rendered this view.:

Try params[:action]. Also, if you don't specify the action, link_to will use the current one.

Railscasts - Free Ruby on Rails Screencasts