2009-11-14 16 views
5

Ruby on Rails ActiveRecord model ilişkilerinde açıklanabilen bir ilişki mi?Bu ilişki Ruby on Rails'de açıklanabilir mi?

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

Şöyle verileri olabilir Böylece:

Adres:

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 | 

Müşteri:

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

ben kendi tabloda adreslerini saklamak istedikleri için veriler müşteriler arasında paylaşılabilir (özellikle teslimat adresi). Ancak, belirli bir müşteri için sadece iki adres bile olabilir.

Başka bir yol olmadığı sürece çoktan çoğa ilişkiden kaçınmak istiyorum. Böyle

cevap

2

Verilen tablo tanımları:

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 

Böyle müşteri ile bir faturalandırma ve sevkiyat adresini ilişkilendirebilirsiniz:

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

masa tasarımı yardımcı olacaktır. .references "veri türü" nin farkında değildim. – y0mbo

5

Evet, bunu yapmak mükemmel mümkündür. addresses masaya iki yabancı anahtarların shipping_address_id ve ile customers tablo göz önüne alındığında, sizin Customer modeli bu gibi görünebilir:

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

Bu teslimat ve fatura adresleri için bir müşteri referansı aynı adres satırı izin verir ve irade ayrıca birkaç müşterinin adresleri paylaşmasına izin verin.

Güncelleme: Bu gibi adreslere referanslar paylaşırken, muhtemelen adres güncellemelerini nasıl ele alacağınızı dikkatlice düşünmek istersiniz. Örneğinizde, Bob ve Al aynı gönderim adresini paylaşıyor. Şimdi, Bob gönderim adresini güncellerse, muhtemelen Ali'nin adresini değiştirmekten kaçınmak için, mevcut kaydın güncellenmesi yerine, Bob'un yeni adresi için yeni bir Address kaydı oluşturmak isteyebilirsiniz. Bazen, aslında bu durumda her iki müşterinin adresini de güncellemek isteyebilirsiniz, ancak çoğu durumda muhtemelen yapmazsınız. Ayrıca

+0

Tasarım değerlendirmenize katılıyorum. Benim örneğim aslında yaptığım şeyden biraz basitleştirildi; Müşteriler aynı hanehalkında aynı hesabın bir parçası olacaktı. Aynı adresi paylaşabilir veya farklı bir yere gönderilmesini isteyebilirler. – y0mbo

0

The documentation for ActiveRecord associations has a section on has_one vs belongs_to., section on has_onediğer sınıf yabancı anahtar varsa bu ancak kullanılması gerektiğini bahseder. Yani, istediğini modellemek için kullanırsın.

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 

Örnek kullanım:

>> 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

OP, müşteriler arasındaki adresleri paylaşabilmeyi istiyordu, bu yüzden, 'Address' modelindeki ilişkiler 'has_one' yerine' has_many' olmalıdır. –

+0

OP'nin gönderisinden oldukça açık görünmüyor, veri örneğinde paylaşılmakta olan adresleri gösteriyor, yani: has_many, kod örneğinde has_one olduğunu öneriyor. Daha sonra çoktan çoğuna sahip olmayı tercih ettiğini belirtir. Benim düşünceme göre, paylaşılan adresler kötü bir fikir olurdu. Müşteri A, mevcut adresini zip + 4 veya Apt numarası eklemek için güncellediğinde ne olur? –

+0

Evet, paylaşılan adresler kesinlikle zahmetli. Adresleri ve müşterileri ayrı ayrı tablolarda tutmak, açıklık sağlamak için iyi bir fikir olabilir, ancak adres satırlarına yapılan referansların paylaşılması, büyük olasılıkla, adres güncelleştirmelerinin nasıl işleneceğine karar verirken sorunlara neden olacaktır. –