我遇到了 Rails 3.2 关联和 PostgreSQL 外键之间的细微差别,我想确定我了解管理它的最佳方法。
假设一个 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_many
andbelongs_to
来跟踪哪些字段包含哪些外键。删除“父”记录时,不会验证子记录不会成为孤立记录。具有外键约束的 PostgreSQL 要求在删除父级之前,所有子级都与父级“取消链接”。只要外键可以为空,这可以通过在删除父级之前将子级的外键设置为空来实现。
就我而言,我想允许孤儿。我最好忘记数据库约束,还是在删除父项时保留它并取消链接记录有什么价值?