这是一个可以在Ruby on Rails的ActiveRecord模型关系中描述的关系吗?
Customer Address
=================== =========
Billing_Address_Id >------}
}---|- AddressId
Shipping_Address_Id >------}
这样我就可以拥有如下所示的数据:
地址:
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 |
客户:
Id | Name | Billing_Address_Id | Shipping_Address_Id |
=======================================================
1 | Bob | 1 | 1 |
2 | Al | 2 | 1 |
3 | Joe | 3 | 4 |
我想将地址存储在自己的表中,因为数据可能会在客户之间共享(特别是送货地址)。但对于任何给定的客户,甚至只有两个地址。
我希望避免多对多的关系,除非没有别的办法。
答案 0 :(得分:5)
是的,完全可以做到这一点。给定customers
表,其中包含shipping_address_id
和billing_address_id
表的addresses
和Customer
,class Customer < ActiveRecord::Base
belongs_to :billing_address, :class_name => 'Address'
belongs_to :shipping_address, :class_name => 'Address'
end
模型可能如下所示:
Address
这将允许客户引用相同的地址行以获取送货地址和帐单地址,并且还允许多个客户共享地址。
更新:在分享对此类地址的引用时,您可能需要仔细考虑如何处理地址更新。在您的示例中,Bob和Al共享相同的送货地址。现在,如果Bob更新了他的送货地址,您可能想要为Bob的新地址创建新的{{1}}记录,而不是更新现有记录,以避免更改Al的地址。有时,在这种情况下,您实际上可能想要更新两个客户的地址,但在大多数情况下,您可能不会这样做。
答案 1 :(得分:2)
给出如下的表定义:
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
您可以将结算和送货地址与您的客户相关联,如下所示:
class Customer < ActiveRecord::Base
belongs_to :shipping_address, :class_name => "Address"
belongs_to :billing_address, :class_name => "Address"
end
答案 2 :(得分:0)
The documentation for ActiveRecord associations has a section on has_one
vs belongs_to
.此外,section on has_one
提到仅当其他类具有外键时才应使用此选项。因此,为了模拟你想要的东西,你可以使用。
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
使用示例:
>> 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">
>>