Topic: Including Associations in List action

Howdy Everybody,
  I'm very new to Rails, though I've had lots of experiencing developing MVC apps with PHP (smarty) and Java (spring/hibernate).  I'm still trying to get my head around some of the framework vagaries.  I'm having trouble understanding exactly how associations get passed around in the MVC framework. For example, I'm writing an app to manage survey replies.  One of the columns in my "replies" table is country_id, indicating a numerical representation of the respondee's country that matches up with "id" in the "countries" table.  The countries table contains id, the name of the country and the name of the region of that country.  Obviously, many different replies could contain the same country_id.  So, for my models:

class Reply < ActiveRecord::Base
  belongs_to :country
end
class Country < ActiveRecord::Base
  has_many :replies
end

I believe this would be the correct relationship.  The first thing I notice is that if I generate scaffold for Reply, it does not display the field country_id for action "list".  Does rails automatically treat fields with "_id" differently?

Secondly, I would like to know what I have to override to display the country name from the countries table and not the country_id from the replies table.

Thanks in advance!

Re: Including Associations in List action

It looks like you have everything setup correctly but you will have to manually add any foreign key elemnts to your forms. Rails doesn't do that automatically (that I know of anyway).

Put this code in your controller:

@countries = Country.find(:all)

And this goes in your view:
<%= collection_select :reply, :country_id, @countries, :id, :name %>

That is assuming your have column called "Name" in your countries table and that is the value you want to display in the select box.

Most code examples are usually pulled out of the air and not tested. Use at your own risk!

Re: Including Associations in List action

Thanks for the quick response, that was very helpful!

As far as the code you suggested for my view, it seems to me that that would be appropriate for the edit (_form.rhtml) view, correct?

What about the code for my list view template?  Obviously I don't want a select box there, I just want it to put in the appropriate foreign key.  My current list controller creates a modified content_columns so that it only displays the columns I need.  Then in the view (the default scaffold view list.rhtml), it iterates over reply and then content_column to format the table.  So, if I am using an associated foreign key:

1) How can I add that foreign key column name to content_columns?
2) Is it possible to still iterate through content_columns and have it associate with the correct value, or will I have to manually put in the fields I want instead of iterating over content_columns?

A little more clarification is probably needed.  My current list.rhtml:

<% for reply in @replies %>
  <tr>
  <% for column in Reply.content_columns %>
    <td><%=h reply.send(column.name) %></td>
  <% end %>
    <td><%= link_to 'Show', :action => 'show', :id => reply %></td>
    <td><%= link_to 'Edit', :action => 'edit', :id => reply %></td>
    <td><%= link_to 'Destroy', { :action => 'destroy', :id => reply }, :confirm => 'Are you sure?', :post => true %></td>
  </tr>
<% end %>

Versus a modified list.rhtml with only the fields I want hard coded (instead of using content_columns) :

<% for reply in @replies %>
  <tr>
    <td> <% reply.name %> </td>
    <td> <% reply.email %> </td>
    <td> <% reply.phone %> </td>
    <td> <% country.name %> </td>
  </tr>
<% end %>

I hope this makes sense.  Thanks again!

Re: Including Associations in List action

I typically don't use scaffolding so I have not used content_columns. Someone with more experience might be able to better answer your question. My suggestion would be to manually create your list table, but that's just me smile

Most code examples are usually pulled out of the air and not tested. Use at your own risk!

Re: Including Associations in List action

That's cool, but with the associations in place, would the 2nd code snipped above work:

(excerpt)

<td><% country.name %></td>

Re: Including Associations in List action

<td><%= country.name %></td>

You're leaving out the '=' in the opening embedded ruby tag.  Without the equal sign nothing is sent to the display...

My RoR journey  -- thoughts on learning RoR and lessons learned in applying TDD and agile practices.

Re: Including Associations in List action

Ok, so the crux of this problem is, given the following model:

class Reply < ActiveRecord::Base
  belongs_to :country
end
class Country < ActiveRecord::Base
  has_many :replies
end

What needs to go in my reply_controller to supply the proper country so that I can do the following in my view?

<td><%= reply.country.name %> </td>

or

<td><%= country.name %> </td>


With my current reply_controller (just @replies = Reply.find(:all)), rails complains that country is a nil object in my view.  Do I just need to do @countries = Country.find(:all) in my reply_controller?

Re: Including Associations in List action

That should just work.  Your reply table does have a country_id column, correct? and it has a non-null value, right?
(Refering to the reply.country.name form..... and that is inside your "for reply in @replies do" loop right?)

Perhaps try

@replies = Reply.find :all, :include=>countries

but that should be a possibly useful optimization, without changing user-visible behavior.

perhaps try running your replies = Reply.find :all in the console and inspect the returned array to see what looks wrong.

Last edited by NielsenE (2006-06-30 07:42:20)

My RoR journey  -- thoughts on learning RoR and lessons learned in applying TDD and agile practices.