Navigating Associations in Scaffolding

In a scaffold generated list.rhtml only the content_columns are displayed. I modified that to show all columns, but the drawback is that for foreign keys you only see the ID, not any thing descriptive. That is, if I have books which belong_to authors, then what I see from the list.rhtml is author_id, not author_name.

I’ve been working to get around that because I can save a lot of time if the joins work magically. So, I wrote some code that basically looks at a column, if it’s an “id column”, then it walks the association to find the object. Once found, it looks for some logical text to display, and if none is found then defaults to the ID.

I've put the code below, but I can’t believe Rails doesn’t provide a way to do this automagically...it seems like something that would be used so often. Anyone?

Anyhow Scaffold makes this:

<% for document_content_template in @ document_content_templates %>

<% for column in DocumentContentTemplate.content_columns %>
<%=h document_content_template.send(column.name) %>
<% end %>
[... snipped show-edit-destroy ]

<% end %>


Which I’ve changed to this:

<% for document_content_template in @document_content_templates %>

<% for column in DocumentContentTemplate.columns %>
<%=h display_column_text(column, document_content_template) %>
<% end %>
[... snipped show-edit-destroy ]

<% end %>


With these helpers:

1  def display_column_text(column, object)
2 if column.name[-3, 3] != "_id"
3 object.send(column.name)
4 else
5 value_from_join(column, object)
6 end
7 end
8
9 def value_from_join(column, object)
10 h = column.name.sub(/_id/, '') # strip off the id
11 r = object.send(h) # get the object
12
13 if (defined? r.name != nil)
14 r.name
15 elsif (defined? r.description != nil)
16 r.description
17 else
18 r.id
19 end
20 end

P.S. Yes, I realize there might be a bug on line 10.
P.P.S There’s actually a potentail bug on line 11 as well…what happens if you have a controller that’s like this:

belongs_to :model_name, :foreign_key => "some_other_id"

which will throw this error:
undefined method `some_other' for #<ModelName:0x47a8650>


UPDATE: the bug on line 11 can easily be handled like so:
begin                               # get the object
r = object.send(h)
rescue
return object.send(column.name)
end


Again, I can’t believe Rails doesn’t the magic to navigate around these objects more gracefully. Thoughts or comments anyone???

No comments: