为Rails模型定义外键关系

62
我有一个Comment类,Post类中的 :foreign_key 是 post_id。
class Comment < ActiveRecord::Base
  belongs_to :post, :class_name => "Post", :foreign_key => "post_id", :counter_cache => true
  belongs_to :author, :class_name => "User", :foreign_key => "author_id"
end

但是我的CreateComments迁移没有定义数据库级别的外键:

class CreateComments < ActiveRecord::Migration
  def self.up
    create_table :comments do |t|
      t.column "post_id",       :integer,   :default => 0, :null => false
      t.column "author",        :string,    :default => "",   :limit => 25, :null => false
      t.column "author_email",  :string,    :default => "",   :limit => 50, :null => false
      t.column "content",       :text,      :null => false
      t.column "status",        :string,    :default => "",   :limit => 25, :null => false
      t.timestamps
    end
  end

  def self.down
    drop_table :comments
  end
end

相反,post_id只是一个简单的整数列。

因此,似乎这个外键关系只存在于Rails的思想中,而不是在数据库层面上存在。

这是正确的吗?

另外,对于相应的Post模型是否需要使用:foreign_key属性声明其与Comments的相互外键关系,还是可以省略?

class Post < ActiveRecord::Base
  set_table_name("blog_posts")
  belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
  has_many :comments, :class_name => "Comment",
    :foreign_key => 'post_id', :order => "created_at desc", :dependent => :destroy
  has_many :categorizations
  has_many :categories, :through => :categorizations
  named_scope :recent, :order => "created_at desc", :limit => 5

end

1
我分享你的惊讶,Rails不使用SQL外键。这使得在数据库上使用非Rails工具变得困难。 - Greg
4
Rails 遵循“所有业务逻辑都应在应用程序中定义”的约定... 因此,它仅将数据库作为“哑存储”使用。没有外键、没有存储过程、没有约束(例如在 postgres 中支持的)。编辑:刚刚发现这个回答说了同样的话- https://dev59.com/hl3Va4cB1Zd3GeqPD9DY - Dalibor Filus
1
https://github.com/matthuhiggins/foreigner - wberry
1个回答

83

Rails的默认行为是,用于保存模型外键的列名是关联名加上后缀_id:foreign_key选项允许您直接设置外键的名称。您的PostComment模型类之间的关联应该如下所示:

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

—请注意,在你的Comment模型中不需要 :class_name => "Post"。Rails已经有了这个信息。只有在需要覆盖Rails惯例时,你才需要指定:class_name:foreign_key

你是正确的,Rails已经为你维护了外键关系。如果你想在数据库层面强制执行它们,可以通过添加外键约束来实现。


由于foreign_key连接只存在于Rails中,而不是数据库级别上。如果从Post中删除一条记录,那么其关联的comment行也会被删除吗?这是维护foreign_key的另一个好处。我能得到这个好处吗? - Shruts_me
2
如果你想同时删除关联的列,需要在编写关联行末尾添加 dependent: destroy - Lavika

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接