views:

304

answers:

3

I've got two models:

Customer and Contact

Customers table has columns :id, :firstName, :lastName

Contacts table has columns :id, :cid, :hphone, :cphone

So if Customers table has data

1  Josh   McDonnel

Then Contacts table has corresponding

5   1   947-245-2342 342-543-8585 

What associations can I use here?

Will Contact have

belongs_to :customer, :foreign_key => "id", :class_name => "Customer"

What should the Customer class have?

Also, how will a simple find_byXXX look like if I want to get all customers (firstName, lastName and corresponding hphone and cphone)

+1  A: 

remember one rule: The table with the foreign key in it belongs_to the table that that foreign key references.

A: 

The object who's table contains the foreign key "belongs_to" the object which doesn't.

If Customer has_one Contact and Contact belongs_to Customer then the foreign key ("customer_id" by default) will exist in the contacts table.

You probably don't want to use "id" as the foreign key because "id" is reserved for the column containing the id of the contact. Specifying a classname is not required either, because the name of the class is the same as the name of the relation (in this case, "customer").

Customer would have:

has_one :contact

Contact would have:

belongs_to :customer

Then if you wanted to find a certain customer's contact you could just call:

@customer.contact

or vice versa.

Your other question regarding find_by_XXX is a little vague. If you want to find all Customers with the first name "John" you could use:

@customers_named_john = Customer.find_by_firstName("John")

But I'm not sure this is what you're asking about.

Austin Fitzpatrick
In his database schema, it appears he wants to store the `id` of the `Customer` in `cid`.
Doug Neiner
+2  A: 

You are close, but your belongs_to should be this. :foreign_key should be the name of the field storing a reference to the primary id:

belongs_to :customer, :foreign_key => "cid"

And in your Customer.rb class:

has_one :contact, :foreign_key => "cid"

Finally, your search might look like this:

@customers = Customer.all(:include => :contact)

Then you could use it in a loop in your view:

<% @customers.each do |customer| %>
   <p>Name: <%= customer.firstName %> <%= customer.lastName %></p>
   <p>Home: <%= customer.contact.hphone %></p>
   <p>Work: <%= customer.contact.cphone %></p>
<% end %>

Incidentally, if you had used customer_id instead of cid your association could just be:

#Contact.rb
belongs_to :customer

#Customer.rb
has_one :contact
Doug Neiner
thanks for a great explanation. I am trying to do the search you suggested but in my case `cid` is varchar but `id` is integer. so that search does not work and throws error. I can go back and change cid to integer but say, for example i did not want to change that. what would be the work around?
Omnipresent
Sure, just run a migration. (BACKUP YOUR DATA FIRST!) Run this: `script/generate migration ChangeContactsForeignKey` and use this code: http://pastie.org/790513
Doug Neiner
Of course, use `rake db:migrate` when you have finished those steps
Doug Neiner
@doug I am having problem when trying to get all customers which have some phone number. This is what I'm doing: http://pastie.org/790718
Omnipresent
@Omnipresent http://pastie.org/790728 Just remember since it is a `has_one` the `include` should reference `:contact` singular, but the SQL conditions should reference the table name, which is plural.
Doug Neiner
thanks. this is so cool. I do not want to do find_by_sql :)
Omnipresent