Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can this relationship be described in Ruby on Rails?

Is this a relationship that can be described in Ruby on Rails' ActiveRecord model relationships?

   Customer                          Address
   ===================               =========
   Billing_Address_Id  >------}
                              }---|- AddressId
   Shipping_Address_Id >------}

So that I could have data that looks like this:

Address:

   Id | Addr           | City     | State | Zip   |
   ================================================
   1  | 123 Main       | New York | NY    | 99999 |
   2  | 200 2nd Street | New York | NY    | 99999 |
   3  | 300 3rd Street | Albany   | NY    | 99998 |
   4  | PO Box 4       | Albany   | NY    | 99998 |

Customer:

   Id | Name | Billing_Address_Id | Shipping_Address_Id  |
   =======================================================
   1  | Bob  | 1                  | 1                    |
   2  | Al   | 2                  | 1                    |
   3  | Joe  | 3                  | 4                    |

I want to store addresses in their own table because the data may be shared across customers (shipping address especially). But there would only even be two addresses for any given customer.

I'd like to avoid a many-to-many relationship unless there is no other way.

like image 211
y0mbo Avatar asked Nov 14 '09 16:11

y0mbo


2 Answers

Yes, it's perfectly possible to do that. Given a customers table with the two foreign keys shipping_address_id and billing_address_id to the addresses table, your Customer model could look like this:

class Customer < ActiveRecord::Base
  belongs_to :billing_address, :class_name => 'Address'
  belongs_to :shipping_address, :class_name => 'Address'
end

This will let a customer reference the same address row for shipping and billing addresses, and will also let several customers share addresses.

Update: When sharing references to addresses like this you'll probably want to carefully consider how to handle address updates. In your example, Bob and Al share the same shipping address. Now, if Bob updates his shipping address you probably want to create a new Address record for Bob's new address rather than update the existing record, to avoid changing Al's address too. Sometimes, you actually might want to update both customers' addresses in this situation, but in most cases you probably don't.

like image 71
Pär Wieslander Avatar answered Sep 30 '22 05:09

Pär Wieslander


Given table definitions like this:

create_table :addresses do |t|
  t.string :street
  t.string :city
  t.string :state
  t.string :zip
  t.timestamps
end

create_table :customers do |t|
  t.string     :name
  t.references :shipping_address
  t.references :billing_address
  t.timestamps
end

You can associate a billing and shipping address with your customer like this:

class Customer < ActiveRecord::Base
  belongs_to :shipping_address, :class_name => "Address"
  belongs_to :billing_address,  :class_name => "Address"
end
like image 39
Ryan McGeary Avatar answered Sep 30 '22 05:09

Ryan McGeary