2009-11-14 9 views
5

Si tratta di una relazione che può essere descritta nelle relazioni del modello ActiveRecord di Ruby on Rails?Questa relazione può essere descritta in Ruby on Rails?

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

così che ho potuto disporre di dati che assomiglia a questo:

Indirizzo:

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 | 

clienti:

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

voglio per memorizzare gli indirizzi nella propria tabella perché i dati possono essere condivisi tra i clienti (indirizzo di spedizione in particolare). Ma ci sarebbero solo due indirizzi per ogni cliente.

Vorrei evitare una relazione molti-a-molti, a meno che non ci sia un altro modo.

risposta

2

definizioni tabella riportata come questo:

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 

È possibile associare un indirizzo di fatturazione e di spedizione con il cliente in questo modo:

class Customer < ActiveRecord::Base 
    belongs_to :shipping_address, :class_name => "Address" 
    belongs_to :billing_address, :class_name => "Address" 
end 
+0

Il design del tavolo sarà di aiuto. Non ero a conoscenza del "tipo di dati" .references. – y0mbo

5

Sì, è perfettamente possibile farlo. Dato un tavolo customers con le due chiavi esterne shipping_address_id e al tavolo addresses, il vostro modello Customer potrebbe essere la seguente:

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

Questo permetterà un riferimento cliente la stessa riga indirizzo per gli indirizzi di spedizione e fatturazione, e la volontà lascia anche che diversi clienti condividano gli indirizzi.

Aggiornamento: Quando si condivide riferimenti a indirizzi come questo probabilmente si vorrà considerare attentamente come gestire gli aggiornamenti di indirizzo. Nel tuo esempio, Bob e Al condividono lo stesso indirizzo di spedizione. Ora, se Bob aggiorna il suo indirizzo di spedizione, probabilmente vorrai creare un nuovo record Address per il nuovo indirizzo di Mario piuttosto che aggiornare il record esistente, per evitare di cambiare anche l'indirizzo di Al. A volte, potresti voler aggiornare gli indirizzi di entrambi i clienti in questa situazione, ma nella maggior parte dei casi probabilmente no.

+0

Sono d'accordo con la tua valutazione del progetto. Il mio esempio è un po 'semplificato da quello che farò in realtà; i clienti sarebbero effettivamente parte dello stesso account nella stessa famiglia. Possono condividere lo stesso indirizzo o possono voler spedire in un altro luogo. – y0mbo

0

The documentation for ActiveRecord associations has a section on has_one vs belongs_to. Inoltre, la section on has_one menzioni che questo dovrebbe essere utilizzato solo se l'altro classe ha la chiave esterna. Quindi, per modellare ciò che vuoi, useresti.

class Address < ActiveRecord::Base 
    has_one :shipto_customer, :class_name => "Customer", :foreign_key => "shipping_address_id" 
    has_one :billto_customer, :class_name => "Customer", :foreign_key => "billing_address_id" 
end 

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

Esempio di utilizzo:

>> customer = Customer.new(:name => "John Smith", 
?>  :shipping_address => Address.new(:address => "123 M St", 
?>  :city => "Phoenix", :state => "AZ", :zip => "85015"), 
?>  :billing_address => Address.new(:address => "555 W Main Dr", 
?>  :city => "Phoenix", :state => "AZ", :zip => "85015") 
>> ) 
=> #<Customer id: nil, name: "John Smith", billing_address_id: nil, shipping_address_id: nil, created_at: nil, updated_at: nil> 
>> customer.save 
    Address Create (0.8ms) INSERT INTO "addresses" ("address", "city", "zip", "created_at", "updated_at", "state") VALUES('555 W Main Dr', 'Phoenix', '85015', '2009-11-14 17:03:28', '2009-11-14 17:03:28', 'AZ') 
    Address Create (0.2ms) INSERT INTO "addresses" ("address", "city", "zip", "created_at", "updated_at", "state") VALUES('123 M St', 'Phoenix', '85015', '2009-11-14 17:03:28', '2009-11-14 17:03:28', 'AZ') 
    Customer Create (0.2ms) INSERT INTO "customers" ("name", "billing_address_id", "shipping_address_id", "created_at", "updated_at") VALUES('John Smith', 1, 2, '2009-11-14 17:03:28', '2009-11-14 17:03:28') 
=> true 
>> customer.shipping_address 
=> #<Address id: 2, address: "123 M St", city: "Phoenix", state: "AZ", zip: "85015", created_at: "2009-11-14 17:03:28", updated_at: "2009-11-14 17:03:28"> 
>> customer.billing_address 
=> #<Address id: 1, address: "555 W Main Dr", city: "Phoenix", state: "AZ", zip: "85015", created_at: "2009-11-14 17:03:28", updated_at: "2009-11-14 17:03:28"> 
>> 
+0

L'OP voleva essere in grado di condividere gli indirizzi tra i clienti, quindi le relazioni nel modello 'Address' dovrebbero essere' has_many' piuttosto che 'has_one'. –

+0

Non sembra abbastanza chiaro dal post dell'OP, nell'esempio di dati mostra gli indirizzi che sono condivisi, ovvero: has_many, nell'esempio di codice che sta suggerendo has_one. Quindi afferma che preferirebbe non avere molti a molti. Secondo me, gli indirizzi condivisi sarebbero una cattiva idea. Cosa succede quando il cliente A aggiorna il suo attuale indirizzo per aggiungere un zip + 4 o un numero di Apt? –

+0

Sì, gli indirizzi condivisi sono sicuramente fastidiosi. Mantenere indirizzi e clienti in tabelle separate è probabilmente una buona idea per chiarezza, ma la condivisione dei riferimenti alle righe di indirizzo causerà molto probabilmente dei problemi nel decidere come gestire gli aggiornamenti degli indirizzi. –