5

这是可以在 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                    |

我想将地址存储在他们自己的表中,因为数据可能会在客户之间共享(尤其是送货地址)。但是对于任何给定的客户,甚至只有两个地址。

除非没有其他办法,否则我想避免多对多的关系。

4

3 回答 3

5

是的,完全有可能做到这一点。给定一个customers包含两个外键shipping_address_id和表billing_address_idaddresses表,您的Customer模型可能如下所示:

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.

于 2009-11-14T16:55:41.127 回答
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
于 2009-11-14T16:55:13.777 回答
0

The documentation for ActiveRecord associations has a section on has_one vs belongs_to. In addition, the section on has_one mentions that this should be used only if the other class has the foreign key. So, to model what you want, you would use.

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

Example usage:

>> 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">
>> 
于 2009-11-14T17:05:43.663 回答