-1

I have a standard table layout that I would like to use on my index view for 4 different resources. I have created an index_table partial that uses locals to supply the:

  • Table title
  • Table headers
  • Tables objects (such as @users)
  • Table cells

<%= render 'shared/index_table', scope_title: 'All Debts', table_headers: ['ID', 'Debtor', 'Amount', 'Status', 'Stage', ''], table_objects: @debts, table_cells: ['id', 'debtor.name', 'amount', 'status', 'stage'] %>

All but the table cells are working and naturally the problem I am running into is the cell is being displayed as Object.id, rather than the actual object id.

<table class="table table-striped table-bordered table-hover" id="sample_3">
    <thead>
        <tr>
          <% table_headers.each do |table_header| %>
            <th> <%= table_header %> </th>
          <% end %>
        </tr>
    </thead>
    <tbody>
      <% table_objects.each do |object| %>
        <tr>
          <% table_cells.each do |cell| %>
            <td> <%= object %>.<%= cell %> </td>
          <% end %>
          <td>
            <a href="javascript:;" class="btn btn-outline btn-sm blue">
            <i class="fa fa-share"></i> View </a>
            <a href="javascript:;" class="btn btn-outline btn-sm green-jungle">
            <i class="fa fa-edit"></i> Edit </a>
            <a href="javascript:;" class="btn btn-outline btn-sm red-mint">
            <i class="fa fa-trash"></i> Delete </a>
          </td>
        </tr>
      <% end %>
    </tbody>
</table>

Any input would be greatly appreciated.

Also is there a more elegant way of doing this, or is this something that is even suggested?

Thanks for your help!

Josh
  • 55
  • 1
  • 4

1 Answers1

0

Change

<td> <%= object %>.<%= cell %> </td>

To

<td> <%= object.send(cell) %> </td>

EDIT

I was trying to answer your question easily but I'll go more in depth as to how you should be doing this entire thing. The way you've set this up in the first place is not exactly "proper" and most likely the reason this question got down-voted.

The first thing is that you don't want to supply all these variables via locals. It gets cumbersome and the view is not the place for this logic. You know what list of models you're sending into the partial so just pass that in for all of your 4 cases in which you call the partial. Come up with a name that encapsulates what all 4 types of objects represent but for the example I'll call it objects like you had.

<%= render 'shared/index_table', objects: @debts %>

Now in your models, make a display method for each attribute that you want to display in the partial.

def self.scope_title 
  'All Debts'
end

def self.table_headers
  ['ID', 'Debtor', 'Amount', 'Status', 'Stage', '']
end

def table_cells
  [id, debtor.name, amount, status, stage]
end

Having these in your model does a few things.

  1. You can test these methods
  2. You can write custom logic where it belongs
  3. Fields will be evaluated as if there was a self. in front of them. That means that your debtor.name field will return it's value in the array.

On that last point, you can also check if debtor exists here so that it doesn't break if there is no relationship: debtor.try(:name)

Now in your view

<% objects.first.class.table_headers.each do |table_header| %>

<% objects.each do |object| %>
    ...
    <% object.table_cells.each do |cell| %>
        <td> <%= cell %> </td>

Last 2 optimizations that are outside the scope of this question:

  1. Make a superclass class ObjectDisplay (change the name Object) and put these display methods in it as stubs.
  2. Make display classes for each type of object and make the display methods in them. class DebtDisplay < ObjectDisplay
James Klein
  • 612
  • 4
  • 15
  • Hi James, Thank you for the most part this worked. The only issue I have hit is if I want to reference a method on a cell that is another object. For example debtor.name does not work, all the others do :) – Josh Feb 25 '16 at 08:22
  • Amazing - thank you so much. I appreciate the guidance on the better practice as this was what I was looking for. – Josh Feb 25 '16 at 20:30