2009-11-14 13 views
5

これはRuby on RailsのActiveRecordモデルの関係で記述できる関係ですか?この関係はRuby on Railsで記述できますか?

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     | 

が、私は自分のテーブルにアドレスを格納したいので、データは顧客間で共有されてもよい(特に配送先住所)。しかし、特定の顧客には2つのアドレスしか存在しません。

他の方法がない限り、多対多の関係を避けたいと思います。このような

答えて

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

テーブルデザインが役立ちます。私は.references "データ型"を知らなかった。 – y0mbo

5

はい、それはそれを行うことは完全に可能です。 addressesテーブルに2つの外部キーshipping_address_idととcustomersテーブルを考えると、あなたのCustomerモデルは次のようになります。

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

これは、顧客が配送先住所、請求先住所のために同じアドレス行を参照してみましょう、と意志ますまた、複数の顧客がアドレスを共有できるようにします。

更新:このようなアドレスへの参照を共有するときは、アドレスの更新をどのように扱うかを慎重に検討することをお勧めします。あなたの例では、BobとAlは同じ配送先アドレスを共有しています。 Bobさんが配送先住所を更新すると、Alのアドレスも変更されないように、既存のレコードを更新するのではなく、Bobの新しい住所の新しいAddressレコードを作成することをお勧めします。場合によっては、実際にこの状況で両方の顧客のアドレスを更新したいと思うかもしれませんが、ほとんどの場合、おそらくそうしないでしょう。

+0

私はあなたの設計評価に同意します。私の例は、私が実際にやっていることから少し簡略化されています。顧客は実際には同じ家庭の同じアカウントの一部になります。同じ住所を共有している場合や、別の場所に配送したい場合があります。 – y0mbo

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"> 
>> 
+0

OPは顧客間でアドレスを共有できるようにしたいので、 'Address'モデルの関係は' has_one'関係よりも 'has_many'でなければなりません。 –

+0

OPのポストからは明らかではないようです。データの例では、アドレスが共有されていることを示しています。つまりhas_manyというコード例では、has_oneを示唆しています。それから彼は多かれ少なかれ多くを持っていないと述べています。私の意見では、共有アドレスは悪い考えです。顧客Aが現在の住所を更新してZIP + 4またはApt番号を追加するとどうなりますか? –

+0

はい、共有アドレスは間違いなく面倒です。アドレスと顧客を別々のテーブルに保管することは、分かりやすくするためには良い考えですが、アドレス行への参照を共有すると、アドレス更新の処理方法を決定する際に問題が発生しやすくなります。 –

関連する問題