什么是RoR最佳实践?按ID或不同列匹配?

时间:2010-05-11 16:09:21

标签: ruby-on-rails activerecord

我度过了一个糟糕的早晨。很多关于为什么事情不起作用的电子邮件。经过调查,我发现存在导致错误的数据不匹配。

方案 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时(例如ID为500),Address将添加一些其他ID(比如425)...现在您不知道哪个地址属于哪个客户。

问题 作为Rails的新手,我想问一下,创建一个额外的列来加入记录总是被认为是好的,而不是依赖于自动递增的列?如果我在Address表中有一个单独的列,我会手动插入最近添加的客户ID,那么这个问题就不会出现了。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

Rails的约定是每个表都有一个名为id的自动递增整数主键列,另外 - 在您的示例中 - addresses表具有非自动递增整数名为customer_id的外键列。顾名思义,它保存了customers表中相关记录的主键值。

如果您遵循这些规则,则无需在关联中指定:foreign_key选项。