views:

46

answers:

2

I am new with rails and trying to understand its :has_many and :belongs_to functionalities.

If I have 3 tables: Customers, Physicians, Addresses

Each customer and each physician will have one address. So it is a one-to-one relationship.

customer_id and physician_id will match address_id

So if I want address of a customer with id 3. I'd say

select * from customer, addresses 
where customer_id = 3 and customer.customer_id = addresses.address_id

How will I translate this into rails code?

I'll have 3 models Customer, Physician, Address

But I am not sure as to what the relationship be? How will i translate the above query to rails find function?

Customer.find (:all, ......?
A: 

Just quickly... you meant in your SQL query "customer.address_id = addresses.address_id" right?

When you put

has_one :address

into the Customer model and

belongs_to :customer

in the Address model, you do the same find as usual, but you can refer to it like:

@cust = Customer.find(params[:id])
street = @cust.address.street
city = @cust.address.city

and so on... check out http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html where it says "Is it a belongs_to or has_one association?" for more info.

Kevin
thanks. so in this case i will not need to put anything in the Address model. just a has_one in Customer and Physician will do ?
patrick
Sorry, I think you need to put belongs_to :customer in the Address model.
Kevin
Technically speaking, you don't need to change the address model, but you should so you can refer to things likeaddress.customer.first_namewhich doesn't have a whole lot of utility in this example but it will in other uses.
Kevin
+3  A: 

I wouldn't share the PK between the tables. What if you have Physician (id = 1), Customer (id = 1). Then who gets Address (id = 1). This is the schema I'd propose

Address
-------
id

Customer
--------
id
address_id

Physician
---------
id
address_id

Then, to bind in your class.

class Physician < ActiveRecord::base
  belongs_to :address
end

class Customer < ActiveRecord::base
  belongs_to :address
end

class Address < ActiveRecord::base
  has_one :physician
  has_one :customer

  def customer_address?
    !customer.nil?
  end

  def physician_address?
    !physician.nil?
  end

end

It may look a little backwards, but look at the FK relationships. Address is referenced by Physician and Customer. Not the other way around.

The docs will say that you almost never want a has_one relationship. I use them, but only when I reinforce them with unique IDs in the database. So make sure that you add a migration like the following.

self.up
  add_index :customers, :address_id, :unique => true
  add_index :physicians, :address_id, :unique => true
end

Now, you know that a customer will only ever match to a single address.


Jarrett Meyer
what do the customer_address? and physician_address? in your Address model class do?
patrick
Why wouldn't you use polymorphic associations?
jonnii