2010-05-11 28 views
0

我有一個可怕的早晨。很多電子郵件都圍繞着爲什麼事情不起作用。經過調查,我發現存在導致錯誤的數據不匹配。什麼是RoR最佳實踐?通過id或不同的列匹配?

方案 CustomerAddress兩個表。

Customer包含

class Customer < ActiveRecord::Base 
    has_one :address, :foreign_key => "id"   
end 

Address包含

class Address < ActiveRecord::Base 
    belongs_to :customer, :foreign_key => "cid"  
end 

於是就id兩個表匹配這是默認的,該列是自動遞增。

問題 在編輯頁面上我們有這樣的代碼。

params[:line1] = @customer.first.address.line1 

它失敗了,因爲在地址表中找不到客戶的匹配記錄。我不知道爲什麼會發生這種情況。看來,隨着時間的推移很多記錄沒有被添加到Address表中。現在問題是,當一個新的Customer被添加(比如說500),Address將添加一些其他的ID(比如425)...現在你不知道哪個地址屬於哪個客戶。

問題 作爲新軌,我問是否一直被認爲善於營造加盟的記錄,而不是取決於自動遞增列一個額外的列?如果我在Address表中有獨立的列,我將手動插入最近添加的客戶ID,那麼這個問題就不會出現。

回答

2

has_one - belongs_to關係應該導致「所屬」模型具有「擁有」模型的​​關鍵。換言之,兩個模型中的:foreign_key子句應該是相同的。

如果我有這些:

class Customer < ActiveRecord::Base 
    has_one :address, :foreign_key => 'cid' # note foreign_key same as in Address 
end 
class Address < ActiveRecord::Base 
    belongs_to :customer, :foreign_key => 'cid' # note foreign_key same as in Customer 
end 

那麼我可以這樣做:

>> cust = Customer.create(:name=>'Mr Custard') 
+----+------------+ 
| id | name  | 
+----+------------+ 
| 1 | Mr Custard | 
+----+------------+ 
1 row in set 
>> add = cust.create_address(:line_1 => '42 Some Street', :line_2 => 'Some where') 
+----+-----+----------------+------------+ 
| id | cid | line_1   | line_2  | 
+----+-----+----------------+------------+ 
| 1 | 1 | 42 Some Street | Some where | 
+----+-----+----------------+------------+ 
1 row in set 

檢查:

>> Customer.first.address 
+----+-----+----------------+------------+ 
| id | cid | line_1   | line_2  | 
+----+-----+----------------+------------+ 
| 1 | 1 | 42 Some Street | Some where | 
+----+-----+----------------+------------+ 
1 row in set 
>> Address.first.customer 
+----+------------+ 
| id | name  | 
+----+------------+ 
| 1 | Mr Custard | 
+----+------------+ 

和我的數據庫看起來是這樣的:

sqlite> select * from customers; 
1|Mr Custard 
sqlite> select * from addresses; 
1|1|42 Some Street|Some where 

(對於ActiveRecord結果的漂亮表格輸出來自Hirb,順便說一下)

+0

感謝您的明確解釋。好奇的是,現在你進入並運行以下查詢'更新地址設置id = 100其中id = 1'(這樣做,因爲我部署在heroku上,並厭倦了不得不重置自動增量),所以更新後查詢..你的協會是否仍然有效? – Omnipresent 2010-05-11 16:53:39

+0

無論「id」的值如何,該關聯都應該可以工作。但是很少有很好的理由來修改記錄的主鍵。你不喜歡自動增量的默認行爲? – Tom 2010-05-11 17:55:13

+0

@Tom - OP沒有指定,但不使用約定的最可能原因是涉及到一個傳統模式。否則,我想不出一個不遵循約定的好理由。 – 2010-05-11 21:50:57

1

的Rails的慣例是每個表都在你的榜樣—名爲id和另外—爲addresses表具有非自動遞增的整數外鍵名爲customer_id列設置爲自動遞增的整數主鍵列。顧名思義,它保存customers表中關聯記錄的主鍵值。

如果您遵循這些規則,則不需要在關聯中指定:foreign_key選項。

+0

你會'@address = @ customer.build_address(:line_1 =>'...',:line_2 =>'。 ..')' – 2010-05-11 17:41:31