2009-11-14 5 views
5

Est-ce une relation qui peut être décrite dans les relations du modèle ActiveRecord de Ruby on Rails?Cette relation peut-elle être décrite dans Ruby on Rails?

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

pour que je puisse avoir des données qui ressemble à ceci:

Adresse:

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 | 

Client:

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

Je veux stocker les adresses dans leur propre table, car les données peuvent être partagées entre les clients (adresse de livraison en particulier). Mais il n'y aurait même que deux adresses pour un client donné.

Je voudrais éviter une relation plusieurs-à-plusieurs à moins qu'il n'y ait pas d'autre moyen.

Répondre

2

définitions de table Étant donné comme ceci:

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 

Vous pouvez associer une adresse de facturation et de livraison avec votre client comme ceci:

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

La conception de la table vous aidera. Je n'étais pas au courant du "type de données" .références. – y0mbo

5

Oui, il est tout à fait possible de le faire. Compte tenu d'une table customers avec les deux clés étrangères shipping_address_id et à la table addresses, votre modèle Customer pourrait ressembler à ceci:

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

Cela permettra une référence client la même adresse ligne pour les adresses de livraison et de facturation, et la volonté permet également à plusieurs clients de partager des adresses.

Mise à jour: Lorsque vous partagez des références à des adresses comme celle-ci, vous voudrez probablement examiner attentivement comment gérer les mises à jour d'adresses. Dans votre exemple, Bob et Al partagent la même adresse de livraison. Maintenant, si Bob met à jour son adresse de livraison, vous voulez probablement créer un nouvel enregistrement Address pour la nouvelle adresse de Bob plutôt que de mettre à jour l'enregistrement existant, pour éviter de changer l'adresse d'Al aussi. Parfois, vous voudrez peut-être mettre à jour les adresses des deux clients dans cette situation, mais dans la plupart des cas, vous ne le faites probablement pas.

+0

Je suis d'accord avec votre évaluation de conception. Mon exemple est un peu simplifié par rapport à ce que je vais faire; les clients feraient partie du même compte dans le même ménage. Ils peuvent partager la même adresse, ou peuvent vouloir envoyer à un endroit différent. – y0mbo

0

The documentation for ActiveRecord associations has a section on has_one vs belongs_to. En outre, le section on has_one mentionne que cela ne devrait être utilisé que si la classe autre a la clé étrangère. Donc, pour modéliser ce que vous voulez, vous utiliseriez.

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 

Exemple d'utilisation:

>> 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 souhaitait pouvoir partager des adresses entre clients, de sorte que les relations dans le modèle 'Address' devraient être des relations' has_many' plutôt que des relations 'has_one'. –

+0

Il ne semble pas très clair à partir de la publication de l'OP, dans l'exemple de données, il montre des adresses partagées, c'est-à-dire: has_many, dans l'exemple de code qu'il suggère has_one. Puis il déclare qu'il préférerait ne pas en avoir beaucoup à plusieurs. À mon avis, les adresses partagées seraient une mauvaise idée. Que se passe-t-il lorsque le client A met à jour son adresse actuelle pour ajouter un zip + 4, ou un numéro Apt? –

+0

Oui, les adresses partagées sont définitivement gênantes. Garder les adresses et les clients dans des tableaux séparés est probablement une bonne idée pour plus de clarté, mais le partage de références aux lignes d'adresses causera probablement des problèmes lors du choix de la gestion des mises à jour d'adresses. –