2012-06-12 48 views
1

我遇到了Rails 3.2关联和PostgreSQL外键之间的细微差别,我想确保我理解管理它的最佳方式。如何管理Rails关联和数据库外键约束之间的区别?

假设一个Message类来跟踪它回复的消息。删除“发件人”消息不应删除链中的其他消息,因此没有:dependent => :destroy子句。

class Message < ActiveRecord::Base 
    # from_message_id self-reference 
    has_many :from_messages, :foreign_key => "from_message_id", 
      :class_name => "Message", :inverse_of => :from_message 
    belongs_to :from_message, 
      :class_name => "Message", :inverse_of => :from_messages 

    attr_accessible :from_message_id, subject, body 
end 

现在,如果我创建了两个链接的消息,并删除第一,Rails的只是报告说,它不存在:

m1 = Message.create 
m2 = Message.new 
m2.from_message = m1 
m2.save 
m1.destroy 
m2.from_message 
=> nil 

但是如果我也加入一个实际的外键约束到数据库我迁移:

execute "ALTER TABLE messages ADD CONSTRAINT messages_from_message_fk 
     FOREIGN KEY (from_message_id) REFERENCES messages(id);" 

然后我得到一个相当恶劣的中止,因为关键是仍在使用:

m1 = Message.create 
m2 = Message.new 
m2.from_message = m1 
m2.save 
m1.destroy 
=> ActiveRecord::InvalidForeignKey: PG::Error: ERROR: update or delete on table 
"messages" violates foreign key constraint "messages_from_message_fk" on 
table "messages" 
DETAIL: Key (id)=(2) is still referenced from table "messages". 

这些结论是否正确?

  • 的Rails只使用has_manybelongs_to跟踪哪些领域持有外国键。删除“父”记录时,不会验证子记录不会成为孤儿。

  • 带有外键约束的PostgreSQL要求在删除父项之前,所有子项均与父项“取消关联”。只要外键可以为空,这可以通过在删除父项之前将子项的外键设置为null来完成。

在我的情况,我想允许孤儿。我最好忘记数据库限制,还是在保留它和删除父母时删除记录的链接方面有价值?

回答

0

在我的情况下,我想让孤儿。我最好忘记数据库限制,还是在保留它和删除父母时删除记录的链接方面有价值?

在PostgreSQL中,通过删除外键约束来改变表格,然后用ON DELETE重新添加它SET NULL;在这种情况下,删除将级联将外键设置为空,从而允许孤儿。

+0

感谢您的提示。我会尽力记住,如果/当我回到这个项目。 –

相关问题